https://gcc.gnu.org/g:ed57e5de634eda91f32e0e61724d8f103ef648dd
commit r16-1196-ged57e5de634eda91f32e0e61724d8f103ef648dd Author: Uros Bizjak <ubiz...@gmail.com> Date: Thu Jun 5 22:53:35 2025 +0200 [i386] Improve "mov<mode>cc" expander for DImode immediates [PR120553] "mov<mode>cc" expander uses x86_64_general_operand predicate that limits the range of immediate operands to 32-bit size. The usage of this predicate causes ifcvt to force out-of-range immediates to registers when converting through noce_try_cmove. The testcase: long long foo (long long c) { return c >= 0 ? 0x400000000ll : -1ll; } compiles (-O2) to: foo: testq %rdi, %rdi movq $-1, %rax movabsq $0x400000000, %rdx cmovns %rdx, %rax ret The above testcase can be compiled to a more optimized code without problematic CMOV instruction if 64-bit immediates are allowed in "mov<mode>cc" expander: foo: movq %rdi, %rax sarq $63, %rax btsq $34, %rax ret The expander calls the ix86_expand_int_movcc function which internally sanitizes arguments of emitted logical insns using expand_simple_binop. The out-of-range immediates are forced to a temporary register just before the instruction, so the instruction combiner is then able to synthesize 64-bit BTS instruction. The code improves even for non-exact-log2 64-bit immediates, e.g. long long foo (long long c) { return c >= 0 ? 0x400001234ll : -1ll; } that now compiles to: foo: movabsq $0x400001234, %rdx movq %rdi, %rax sarq $63, %rax orq %rdx, %rax ret again avoiding problematic CMOV instruction. PR target/120553 gcc/ChangeLog: * config/i386/i386.md (mov<mode>cc): Use "general_operand" predicate for operands 2 and 3 for all modes. gcc/testsuite/ChangeLog: * gcc.target/i386/pr120553.c: New test. Diff: --- gcc/config/i386/i386.md | 4 ++-- gcc/testsuite/gcc.target/i386/pr120553.c | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 40b43cf092ac..8eee44756eba 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -26478,8 +26478,8 @@ (define_expand "mov<mode>cc" [(set (match_operand:SWIM 0 "register_operand") (if_then_else:SWIM (match_operand 1 "comparison_operator") - (match_operand:SWIM 2 "<general_operand>") - (match_operand:SWIM 3 "<general_operand>")))] + (match_operand:SWIM 2 "general_operand") + (match_operand:SWIM 3 "general_operand")))] "" "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;") diff --git a/gcc/testsuite/gcc.target/i386/pr120553.c b/gcc/testsuite/gcc.target/i386/pr120553.c new file mode 100644 index 000000000000..abbf58c67223 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr120553.c @@ -0,0 +1,6 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2" } */ + +long long foo (long long c) { return c >= 0 ? 0x400000000ll : -1ll; } + +/* { dg-final { scan-assembler "bts" } } */