My apologies for the inconvenience. The new support for -Oz using
push/pop for small integer constants on x86_64 is only a win/correct
for loading registers. Fixed by adding !MEM_P tests in the appropriate
locations.
This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
and make -k check with no new failures. Ok for mainline?
2021-12-21 Roger Sayle <[email protected]>
gcc/ChangeLog
PR target/103773
* config/i386/i386.md (*movdi_internal): Only use short
push/pop sequence for register (non-memory) destinations.
(*movsi_internal): Likewise.
gcc/testsuite/ChangeLog
PR target/103773
* gcc.target/i386/pr103773.c: New test case.
Roger
--
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index d25453f..e596f8b 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -2217,7 +2217,8 @@
if (optimize_size > 1
&& TARGET_64BIT
&& CONST_INT_P (operands[1])
- && IN_RANGE (INTVAL (operands[1]), -128, 127))
+ && IN_RANGE (INTVAL (operands[1]), -128, 127)
+ && !MEM_P (operands[0]))
return "push{q}\t%1\n\tpop{q}\t%0";
return "mov{l}\t{%k1, %k0|%k0, %k1}";
}
@@ -2440,7 +2441,8 @@
return "lea{l}\t{%E1, %0|%0, %E1}";
else if (optimize_size > 1
&& CONST_INT_P (operands[1])
- && IN_RANGE (INTVAL (operands[1]), -128, 127))
+ && IN_RANGE (INTVAL (operands[1]), -128, 127)
+ && !MEM_P (operands[0]))
{
if (TARGET_64BIT)
return "push{q}\t%1\n\tpop{q}\t%q0";
diff --git a/gcc/testsuite/gcc.target/i386/pr103773.c
b/gcc/testsuite/gcc.target/i386/pr103773.c
new file mode 100644
index 0000000..1e4b8ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr103773.c
@@ -0,0 +1,12 @@
+/* { dg-do run } */
+/* { dg-options "-Oz" } */
+
+unsigned long long x;
+
+int main (void)
+{
+ __builtin_memset (&x, 0xff, 4);
+ if (x != 0xffffffff)
+ __builtin_abort ();
+ return 0;
+}