On Mon, Feb 10, 2025 at 12:26:03AM +0100, Uros Bizjak wrote: > On Sun, Feb 9, 2025 at 11:31 PM Jakub Jelinek <ja...@redhat.com> wrote: > > > > On Sun, Feb 09, 2025 at 09:24:30AM +0100, Uros Bizjak wrote: > > > "For commutative and comparison operators, a constant is always made > > > the second operand." > > > > Isn't that just for commutative comparison operators (eq, ne, ordered, > > unordered, ltgt, uneq)? Compare itself even isn't RTX_COMPARE at all, > > it is RTX_BIN_ARITH, so similar to minus. > > And I must say I can't find where simplify-rtx.cc or combine.cc would be > > trying to canonicalize that order (note, it would need to change the related > > uses of flags as well). > > When combine combines some RTX with any operand of COMPARE RTX, it > canonicalizes COMPARE RTX in simplify_compare_const: > > /* Try to simplify a comparison between OP0 and a constant OP1, > where CODE is the comparison code that will be tested, into a > (CODE OP0 const0_rtx) form. > > The result is a possibly different comparison code to use. > *POP0 and *POP1 may be updated. */ > > This form won't match the new BT RTX. > > At the moment, there is no instruction using compare:CCC that could be > combined with e.g. ZERO_EXTRACT RTX to form "*bt<mode>" insn, so the > canonicalization rules do not matter, because BT is always expanded > from splitters in a kind-of manual way. This is the reason that patch > is OK, but without adding the new form to > ix86_canonicalize_comparison, combine won't be able to match the new > BT RTX in future. > > Please see ix86_canonicalize_comparison for a couple of examples on > how to allow combine to match non-canonical compares.
So, would it be better to represent *bt<mode> as (set (reg:CCC FLAGS_REG) (compare:CCC (not:SWI48 (zero_extract:SWI48 ...)) (const_int -1))) rather than (set (reg:CCC FLAGS_REG) (compare:CCC (const_int 0) (zero_extract:SWI48 ...))) ? Or (set (reg:CCC FLAGS_REG) (compare:CCC (xor:SWI48 (zero_extract:SWI48 ...) (const_int 1)) (const_int 1))) Though, simplify_compare_const has similarly code to transform (ltu something (const_int C)) into (leu something (const_int C-1)) and that would affect both. Or do you want additionally: --- gcc/config/i386/i386.cc 2025-02-07 14:25:03.982866595 +0100 +++ gcc/config/i386/i386.cc 2025-02-10 09:39:36.914272948 +0100 @@ -595,6 +595,19 @@ ix86_canonicalize_comparison (int *code, *code = (int) swap_condition ((enum rtx_code) *code); return; } + + /* BT is represented as + (compare:CCC (const_int 0) (zero_extract ... (const_int 1) ...)) */ + if (!op0_preserve_value + && (*code == GTU || *code == LEU) + && GET_CODE (*op0) == ZERO_EXTRACT + && XEXP (*op0, 1) == const1_rtx + && *op1 == const0_rtx) + { + std::swap (*op0, *op1); + *code = (int) swap_condition ((enum rtx_code) *code); + return; + } } /* Hook to determine if one function can safely inline another. */ or so? But what will care to use CCCmode for this rather than some other? Jakub