On Wed, Oct 14, 2020 at 11:22:48AM +0200, Richard Biener wrote: > > + if (mode == CCCmode > > + && GET_CODE (XEXP (x, 0)) == NEG > > + && GET_CODE (XEXP (XEXP (x, 0), 0)) == GEU > > + && REG_P (XEXP (XEXP (XEXP (x, 0), 0), 0)) > > + && (GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == CCCmode > > + || GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == CCmode) > > + && REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0)) == FLAGS_REG > > + && XEXP (XEXP (XEXP (x, 0), 0), 1) == const0_rtx > > + && GET_CODE (XEXP (x, 1)) == LTU > > + && REG_P (XEXP (XEXP (x, 1), 0)) > > + && (GET_MODE (XEXP (XEXP (x, 1), 0)) > > + == GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0))) > > + && REGNO (XEXP (XEXP (x, 1), 0)) == FLAGS_REG > > + && XEXP (XEXP (x, 1), 1) == const0_rtx) > > Meh ;) templates to the rescue? > > rtx_match < un<NEG, bin<GEU, reg, ..> > ().matches (x) > > and with fancy metaprogramming expand it to above? Not sure if it's easier > to read that way. Maybe
It would certainly not match the style used elsewhere in the backend. > > rtx neg, geu; > if (mode == CCCmode > && (neg = XEXP (x, 0), GET_CODE (neg) == NEG) > && (geu = XEXP (neg, 0), GET_CODE (geu) == GEU) > ... > > or > > if (mode == CCCmode > && GET_CODE (neg = XEXP (x, 0)) == NEG > > thus some manual CSE and naming in this matching would help? Attached are two incremental patches, one just adds op0 and op1 for the COMPARE operand of all the costs COMPARE handling, which replaces all the XEXP (x, 0) with op0 and XEXP (x, 1) with op1, the other is that plus the geu you've suggested. Jakub
--- gcc/config/i386/i386.c.jj 2020-10-14 11:31:38.000000000 +0200 +++ gcc/config/i386/i386.c 2020-10-14 11:37:02.843258215 +0200 @@ -19765,44 +19765,44 @@ ix86_rtx_costs (rtx x, machine_mode mode return false; case COMPARE: - if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT - && XEXP (XEXP (x, 0), 1) == const1_rtx - && CONST_INT_P (XEXP (XEXP (x, 0), 2)) - && XEXP (x, 1) == const0_rtx) + rtx op0, op1; + op0 = XEXP (x, 0); + op1 = XEXP (x, 1); + if (GET_CODE (op0) == ZERO_EXTRACT + && XEXP (op0, 1) == const1_rtx + && CONST_INT_P (XEXP (op0, 2)) + && op1 == const0_rtx) { /* This kind of construct is implemented using test[bwl]. Treat it as if we had an AND. */ - mode = GET_MODE (XEXP (XEXP (x, 0), 0)); + mode = GET_MODE (XEXP (op0, 0)); *total = (cost->add - + rtx_cost (XEXP (XEXP (x, 0), 0), mode, outer_code, + + rtx_cost (XEXP (op0, 0), mode, outer_code, opno, speed) + rtx_cost (const1_rtx, mode, outer_code, opno, speed)); return true; } - if (GET_CODE (XEXP (x, 0)) == PLUS - && rtx_equal_p (XEXP (XEXP (x, 0), 0), XEXP (x, 1))) + if (GET_CODE (op0) == PLUS && rtx_equal_p (XEXP (op0, 0), op1)) { /* This is an overflow detection, count it as a normal compare. */ - *total = rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)), - COMPARE, 0, speed); + *total = rtx_cost (op0, GET_MODE (op0), COMPARE, 0, speed); return true; } if (mode == CCCmode - && GET_CODE (XEXP (x, 0)) == NEG - && GET_CODE (XEXP (XEXP (x, 0), 0)) == GEU - && REG_P (XEXP (XEXP (XEXP (x, 0), 0), 0)) - && (GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == CCCmode - || GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == CCmode) - && REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0)) == FLAGS_REG - && XEXP (XEXP (XEXP (x, 0), 0), 1) == const0_rtx - && GET_CODE (XEXP (x, 1)) == LTU - && REG_P (XEXP (XEXP (x, 1), 0)) - && (GET_MODE (XEXP (XEXP (x, 1), 0)) - == GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0))) - && REGNO (XEXP (XEXP (x, 1), 0)) == FLAGS_REG - && XEXP (XEXP (x, 1), 1) == const0_rtx) + && GET_CODE (op0) == NEG + && GET_CODE (XEXP (op0, 0)) == GEU + && REG_P (XEXP (XEXP (op0, 0), 0)) + && (GET_MODE (XEXP (XEXP (op0, 0), 0)) == CCCmode + || GET_MODE (XEXP (XEXP (op0, 0), 0)) == CCmode) + && REGNO (XEXP (XEXP (op0, 0), 0)) == FLAGS_REG + && XEXP (XEXP (op0, 0), 1) == const0_rtx + && GET_CODE (op1) == LTU + && REG_P (XEXP (op1, 0)) + && GET_MODE (XEXP (op1, 0)) == GET_MODE (XEXP (XEXP (op0, 0), 0)) + && REGNO (XEXP (op1, 0)) == FLAGS_REG + && XEXP (op1, 1) == const0_rtx) { /* This is *setcc_qi_addqi3_cconly_overflow_1_* patterns, a nop. */ *total = 0; @@ -19810,8 +19810,7 @@ ix86_rtx_costs (rtx x, machine_mode mode } /* The embedded comparison operand is completely free. */ - if (!general_operand (XEXP (x, 0), GET_MODE (XEXP (x, 0))) - && XEXP (x, 1) == const0_rtx) + if (!general_operand (op0, GET_MODE (op0)) && op1 == const0_rtx) *total = 0; return false;
--- gcc/config/i386/i386.c.jj 2020-10-14 11:31:38.000000000 +0200 +++ gcc/config/i386/i386.c 2020-10-14 11:41:35.108273970 +0200 @@ -15131,6 +15131,7 @@ ix86_cc_mode (enum rtx_code code, rtx op /* Codes needing carry flag. */ case GEU: /* CF=0 */ case LTU: /* CF=1 */ + rtx geu; /* Detect overflow checks. They need just the carry flag. */ if (GET_CODE (op0) == PLUS && (rtx_equal_p (op1, XEXP (op0, 0)) @@ -15139,16 +15140,15 @@ ix86_cc_mode (enum rtx_code code, rtx op /* Similarly for *setcc_qi_addqi3_cconly_overflow_1_* patterns. */ else if (code == LTU && GET_CODE (op0) == NEG - && GET_CODE (XEXP (op0, 0)) == GEU - && REG_P (XEXP (XEXP (op0, 0), 0)) - && (GET_MODE (XEXP (XEXP (op0, 0), 0)) == CCCmode - || GET_MODE (XEXP (XEXP (op0, 0), 0)) == CCmode) - && REGNO (XEXP (XEXP (op0, 0), 0)) == FLAGS_REG - && XEXP (XEXP (op0, 0), 1) == const0_rtx + && GET_CODE (geu = XEXP (op0, 0)) == GEU + && REG_P (XEXP (geu, 0)) + && (GET_MODE (XEXP (geu, 0)) == CCCmode + || GET_MODE (XEXP (geu, 0)) == CCmode) + && REGNO (XEXP (geu, 0)) == FLAGS_REG + && XEXP (geu, 1) == const0_rtx && GET_CODE (op1) == LTU && REG_P (XEXP (op1, 0)) - && (GET_MODE (XEXP (op1, 0)) - == GET_MODE (XEXP (XEXP (op0, 0), 0))) + && GET_MODE (XEXP (op1, 0)) == GET_MODE (XEXP (geu, 0)) && REGNO (XEXP (op1, 0)) == FLAGS_REG && XEXP (op1, 1) == const0_rtx) return CCCmode; @@ -19765,44 +19765,45 @@ ix86_rtx_costs (rtx x, machine_mode mode return false; case COMPARE: - if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT - && XEXP (XEXP (x, 0), 1) == const1_rtx - && CONST_INT_P (XEXP (XEXP (x, 0), 2)) - && XEXP (x, 1) == const0_rtx) + rtx op0, op1; + op0 = XEXP (x, 0); + op1 = XEXP (x, 1); + if (GET_CODE (op0) == ZERO_EXTRACT + && XEXP (op0, 1) == const1_rtx + && CONST_INT_P (XEXP (op0, 2)) + && op1 == const0_rtx) { /* This kind of construct is implemented using test[bwl]. Treat it as if we had an AND. */ - mode = GET_MODE (XEXP (XEXP (x, 0), 0)); + mode = GET_MODE (XEXP (op0, 0)); *total = (cost->add - + rtx_cost (XEXP (XEXP (x, 0), 0), mode, outer_code, + + rtx_cost (XEXP (op0, 0), mode, outer_code, opno, speed) + rtx_cost (const1_rtx, mode, outer_code, opno, speed)); return true; } - if (GET_CODE (XEXP (x, 0)) == PLUS - && rtx_equal_p (XEXP (XEXP (x, 0), 0), XEXP (x, 1))) + if (GET_CODE (op0) == PLUS && rtx_equal_p (XEXP (op0, 0), op1)) { /* This is an overflow detection, count it as a normal compare. */ - *total = rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)), - COMPARE, 0, speed); + *total = rtx_cost (op0, GET_MODE (op0), COMPARE, 0, speed); return true; } + rtx geu; if (mode == CCCmode - && GET_CODE (XEXP (x, 0)) == NEG - && GET_CODE (XEXP (XEXP (x, 0), 0)) == GEU - && REG_P (XEXP (XEXP (XEXP (x, 0), 0), 0)) - && (GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == CCCmode - || GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == CCmode) - && REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0)) == FLAGS_REG - && XEXP (XEXP (XEXP (x, 0), 0), 1) == const0_rtx - && GET_CODE (XEXP (x, 1)) == LTU - && REG_P (XEXP (XEXP (x, 1), 0)) - && (GET_MODE (XEXP (XEXP (x, 1), 0)) - == GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0))) - && REGNO (XEXP (XEXP (x, 1), 0)) == FLAGS_REG - && XEXP (XEXP (x, 1), 1) == const0_rtx) + && GET_CODE (op0) == NEG + && GET_CODE (geu = XEXP (op0, 0)) == GEU + && REG_P (XEXP (geu, 0)) + && (GET_MODE (XEXP (geu, 0)) == CCCmode + || GET_MODE (XEXP (geu, 0)) == CCmode) + && REGNO (XEXP (geu, 0)) == FLAGS_REG + && XEXP (geu, 1) == const0_rtx + && GET_CODE (op1) == LTU + && REG_P (XEXP (op1, 0)) + && GET_MODE (XEXP (op1, 0)) == GET_MODE (XEXP (geu, 0)) + && REGNO (XEXP (op1, 0)) == FLAGS_REG + && XEXP (op1, 1) == const0_rtx) { /* This is *setcc_qi_addqi3_cconly_overflow_1_* patterns, a nop. */ *total = 0; @@ -19810,8 +19811,7 @@ ix86_rtx_costs (rtx x, machine_mode mode } /* The embedded comparison operand is completely free. */ - if (!general_operand (XEXP (x, 0), GET_MODE (XEXP (x, 0))) - && XEXP (x, 1) == const0_rtx) + if (!general_operand (op0, GET_MODE (op0)) && op1 == const0_rtx) *total = 0; return false;