https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78200
--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> --- So RTL expansion ends up in /* If jumps are cheap and the target does not support conditional compare, turn some more codes into jumpy sequences. */ else if (BRANCH_COST (optimize_insn_for_speed_p (), false) < 4 && targetm.gen_ccmp_first == NULL) { if ((code2 == BIT_AND_EXPR && TYPE_PRECISION (TREE_TYPE (op0)) == 1 && TREE_CODE (gimple_assign_rhs2 (second)) != INTEGER_CST) || code2 == TRUTH_AND_EXPR) { code = TRUTH_ANDIF_EXPR; op0 = gimple_assign_rhs1 (second); op1 = gimple_assign_rhs2 (second); where we could adjust operand order based on the immediately dominating condition. Unfortunately sth as simple as /* We'll expand RTL for op0 first, see if we'd better expand RTL for op1 first. */ if (TREE_CODE (op1) == SSA_NAME && single_pred_p (bb)) { gimple *def1 = SSA_NAME_DEF_STMT (op1); if (is_gimple_assign (def1) && TREE_CODE_CLASS (gimple_assign_rhs_code (def1)) == tcc_comparison) { basic_block pred = single_pred (bb); gimple *last = last_stmt (pred); if (last && gimple_code (last) == GIMPLE_COND && gimple_assign_rhs1 (def1) == gimple_cond_lhs (last)) std::swap (op0, op1); } } doesn't work as the predecessor is no longer in GIMPLE (we dropped the seq for the GIMPLE stmts and GIMPLE_CONDs have no DEFs...). Also I'm not sure the half-way RTL CFG will still point to the original block. Of course the above heuristic is really only applicable if there's not much code expanded between this jump and the one in the predecessor. OTOH if we have the BRANCH_COST check during RTL expansion (similar to what we have for LOGICAL_OP_NON_SHORT_CIRCUIT in fold-const.c) then maybe if-combining shouldn't combine the conditionals. There's a slight disconnect here, the above is BRANCH_COST < 4 while the other is BRANCH_COST >= 2 ... The cfgexpand code could also be done as a pre-pass on the IL turning the straight-line code back to CFG (I guess that's a good idea anyway).