Message ID | CAFULd4b8FD=73-JSwf7J1G8yGwS0AF=2SF0mLZ_-139ebe6ivg@mail.gmail.com |
---|---|
State | New |
Headers | show |
Series | [committed] i386: Return CCmode from ix86_cc_mode for unknown RTX code [PR112494] | expand |
On Mon, Nov 13, 2023 at 10:49:23PM +0100, Uros Bizjak wrote: > Combine wants to combine following instructions into an insn that can > perform both an (arithmetic) operation and set the condition code. During > the conversion a new RTX is created, and combine passes the RTX code of the > innermost RTX expression of the CC use insn in which CC reg is used to > SELECT_CC_MODE, to determine the new mode of the comparison: > > Trying 5 -> 8: > 5: r98:DI=0xd7 > 8: flags:CCZ=cmp(r98:DI,0) > REG_EQUAL cmp(0xd7,0) > Failed to match this instruction: > (parallel [ > (set (reg:CC 17 flags) > (compare:CC (const_int 215 [0xd7]) > (const_int 0 [0]))) > (set (reg/v:DI 98 [ flags ]) > (const_int 215 [0xd7])) > ]) > > where: > > (insn 5 2 6 2 (set (reg/v:DI 98 [ flags ]) > (const_int 215 [0xd7])) "pr112494.c":8:8 84 {*movdi_internal} > (nil)) > > (insn 8 7 11 2 (set (reg:CCZ 17 flags) > (compare:CCZ (reg/v:DI 98 [ flags ]) > (const_int 0 [0]))) "pr112494.c":11:9 8 {*cmpdi_ccno_1} > (expr_list:REG_EQUAL (compare:CCZ (const_int 215 [0xd7]) > (const_int 0 [0])) > (nil))) > > x86_cc_mode (AKA SELECT_CC_MODE) is not prepared to handle random RTX > codes and triggers gcc_unreachable() when SET RTX code is passed to it. > The patch removes gcc_unreachable() and returns CCmode for unknown > RTX codes, so combine can try various combinations involving CC reg > without triggering ICE. > > Please note that x86 MOV instructions do not set flags, so the above > combination is not recognized as a valid x86 instruction. > > PR target/112494 > > gcc/ChangeLog: > > * config/i386/i386.cc (ix86_cc_mode) [default]: Return CCmode. > > gcc/testsuite/ChangeLog: > > * gcc.target/i386/pr112494.c: New test. > > Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. For me the test ICEs with RTL checking on both x86_64-linux and i686-linux. pr112494.c:17:1: internal compiler error: RTL check: expected elt 0 type 'e' or 'u', have 'E' (rtx unspec) in try_combine, at combine.cc:3237 This is on 3236 /* Just replace the CC reg with a new mode. */ 3237 SUBST (XEXP (*cc_use_loc, 0), newpat_dest); 3238 undobuf.other_insn = cc_use_insn; in combine.cc, where *cc_use_loc is (unspec:DI [ (reg:CC 17 flags) ] UNSPEC_PUSHFL) on which XEXP (guess combine assumes CC must be used inside of a comparison). Jakub
On Tue, Nov 14, 2023 at 6:51 PM Jakub Jelinek <jakub@redhat.com> wrote: > > On Mon, Nov 13, 2023 at 10:49:23PM +0100, Uros Bizjak wrote: > > Combine wants to combine following instructions into an insn that can > > perform both an (arithmetic) operation and set the condition code. During > > the conversion a new RTX is created, and combine passes the RTX code of the > > innermost RTX expression of the CC use insn in which CC reg is used to > > SELECT_CC_MODE, to determine the new mode of the comparison: > > > > Trying 5 -> 8: > > 5: r98:DI=0xd7 > > 8: flags:CCZ=cmp(r98:DI,0) > > REG_EQUAL cmp(0xd7,0) > > Failed to match this instruction: > > (parallel [ > > (set (reg:CC 17 flags) > > (compare:CC (const_int 215 [0xd7]) > > (const_int 0 [0]))) > > (set (reg/v:DI 98 [ flags ]) > > (const_int 215 [0xd7])) > > ]) > > > > where: > > > > (insn 5 2 6 2 (set (reg/v:DI 98 [ flags ]) > > (const_int 215 [0xd7])) "pr112494.c":8:8 84 {*movdi_internal} > > (nil)) > > > > (insn 8 7 11 2 (set (reg:CCZ 17 flags) > > (compare:CCZ (reg/v:DI 98 [ flags ]) > > (const_int 0 [0]))) "pr112494.c":11:9 8 {*cmpdi_ccno_1} > > (expr_list:REG_EQUAL (compare:CCZ (const_int 215 [0xd7]) > > (const_int 0 [0])) > > (nil))) > > > > x86_cc_mode (AKA SELECT_CC_MODE) is not prepared to handle random RTX > > codes and triggers gcc_unreachable() when SET RTX code is passed to it. > > The patch removes gcc_unreachable() and returns CCmode for unknown > > RTX codes, so combine can try various combinations involving CC reg > > without triggering ICE. > > > > Please note that x86 MOV instructions do not set flags, so the above > > combination is not recognized as a valid x86 instruction. > > > > PR target/112494 > > > > gcc/ChangeLog: > > > > * config/i386/i386.cc (ix86_cc_mode) [default]: Return CCmode. > > > > gcc/testsuite/ChangeLog: > > > > * gcc.target/i386/pr112494.c: New test. > > > > Patch was bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. > > For me the test ICEs with RTL checking on both x86_64-linux and i686-linux. > pr112494.c:17:1: internal compiler error: RTL check: expected elt 0 type 'e' or 'u', have 'E' (rtx unspec) in try_combine, at combine.cc:3237 > This is on > 3236 /* Just replace the CC reg with a new mode. */ > 3237 SUBST (XEXP (*cc_use_loc, 0), newpat_dest); > 3238 undobuf.other_insn = cc_use_insn; > in combine.cc, where *cc_use_loc is > (unspec:DI [ > (reg:CC 17 flags) > ] UNSPEC_PUSHFL) > on which XEXP (guess combine assumes CC must be used inside of a > comparison). Can you please fill out a bugreport, so the bug can be properly tiaged? I don't think there is anything wrong with new patterns, at least the documentation doesn't say that CC_reg can't be used in unspecs and other non-compare RTXes. Thanks, Uros.
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 2c80fd8ebf3..176ca650aa2 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -16469,12 +16469,9 @@ ix86_cc_mode (enum rtx_code code, rtx op0, rtx op1) return CCNOmode; else return CCGCmode; - /* strcmp pattern do (use flags) and combine may ask us for proper - mode. */ - case USE: - return CCmode; default: - gcc_unreachable (); + /* CCmode should be used in all other cases. */ + return CCmode; } } diff --git a/gcc/testsuite/gcc.target/i386/pr112494.c b/gcc/testsuite/gcc.target/i386/pr112494.c new file mode 100644 index 00000000000..e9482f5d075 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr112494.c @@ -0,0 +1,17 @@ +/* PR target/112494 */ +/* { dg-options "-Og -fno-tree-copy-prop -fno-tree-fre -fno-tree-ccp -fno-tree-forwprop" } */ + +#include <x86intrin.h> + +int main() +{ + long flags = 0xD7; + + __writeeflags(0xD7); + flags && !__readeflags(); + + if ((flags && (!__readeflags())) != 0xD7) + ; + + return 0; +}