summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <roger@nextmovesoftware.com>2022-08-07 08:49:48 +0100
committerRoger Sayle <roger@nextmovesoftware.com>2022-08-07 08:49:48 +0100
commita46bca36b7b3a8a7e15b04225fb2b4f9b1bed62c (patch)
tree467c0d9bfeb4b8ffeeff33f21a27db0eddb19532
parent019a41a7cea5e9855c60b6825b6f2b7378c98eab (diff)
Allow any immediate constant in *cmp<dwi>_doubleword splitter on x86_64.
This patch tweaks i386.md's *cmp<dwi>_doubleword splitter's predicate to allow general_operand, not just x86_64_hilo_general_operand, to improve code generation. As a general rule, i386.md's _doubleword splitters should be post-reload splitters that require integer immediate operands to be x86_64_hilo_int_operand, so that each part is a valid word mode immediate constant. As an exception to this rule, doubleword patterns that must be split before reload, because they require additional scratch registers, can use take advantage of this ability to create new pseudos, to accept any immediate constant, and call force_reg on the high and/or low parts if they are not suitable immediate operands in word mode. The benefit is shown in the new cmpti3.c test case below. __int128 x; int foo() { __int128 t = 0x1234567890abcdefLL; return x == t; } where GCC with -O2 currently generates: movabsq $1311768467294899695, %rax xorl %edx, %edx xorq x(%rip), %rax xorq x+8(%rip), %rdx orq %rdx, %rax sete %al movzbl %al, %eax ret but with this patch now generates: movabsq $1311768467294899695, %rax xorq x(%rip), %rax orq x+8(%rip), %rax sete %al movzbl %al, %eax ret 2022-08-07 Roger Sayle <roger@nextmovesoftware.com> gcc/ChangeLog * config/i386/i386.md (*cmp<dwi>_doubleword): Change predicate for x86_64_hilo_general_operand to general operand. Call force_reg on parts that are not x86_64_immediate_operand. gcc/testsuite/ChangeLog * gcc.target/i386/cmpti1.c: New test case. * gcc.target/i386/cmpti2.c: Likewise. * gcc.target/i386/cmpti3.c: Likewise.
-rw-r--r--gcc/config/i386/i386.md16
-rw-r--r--gcc/testsuite/gcc.target/i386/cmpti1.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/cmpti2.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/cmpti3.c13
4 files changed, 46 insertions, 3 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 298e4b30348..fd30c573c27 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1510,7 +1510,7 @@
(define_insn_and_split "*cmp<dwi>_doubleword"
[(set (reg:CCZ FLAGS_REG)
(compare:CCZ (match_operand:<DWI> 0 "nonimmediate_operand")
- (match_operand:<DWI> 1 "x86_64_hilo_general_operand")))]
+ (match_operand:<DWI> 1 "general_operand")))]
"ix86_pre_reload_split ()"
"#"
"&& 1"
@@ -1544,7 +1544,12 @@
else if (operands[0] == constm1_rtx)
emit_insn (gen_one_cmpl<mode>2 (operands[4], operands[1]));
else
- emit_insn (gen_xor<mode>3 (operands[4], operands[0], operands[1]));
+ {
+ if (CONST_SCALAR_INT_P (operands[1])
+ && !x86_64_immediate_operand (operands[1], <MODE>mode))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+ emit_insn (gen_xor<mode>3 (operands[4], operands[0], operands[1]));
+ }
if (operands[3] == const0_rtx)
operands[5] = operands[2];
@@ -1558,7 +1563,12 @@
else if (operands[2] == constm1_rtx)
emit_insn (gen_one_cmpl<mode>2 (operands[5], operands[3]));
else
- emit_insn (gen_xor<mode>3 (operands[5], operands[2], operands[3]));
+ {
+ if (CONST_SCALAR_INT_P (operands[3])
+ && !x86_64_immediate_operand (operands[3], <MODE>mode))
+ operands[3] = force_reg (<MODE>mode, operands[3]);
+ emit_insn (gen_xor<mode>3 (operands[5], operands[2], operands[3]));
+ }
}
})
diff --git a/gcc/testsuite/gcc.target/i386/cmpti1.c b/gcc/testsuite/gcc.target/i386/cmpti1.c
new file mode 100644
index 00000000000..1c5f121e544
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cmpti1.c
@@ -0,0 +1,8 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2" } */
+int eq(__int128 x, __int128 y) { return x == y; }
+int ne(__int128 x, __int128 y) { return x != y; }
+/* { dg-final { scan-assembler-times "xorq" 4 } } */
+/* { dg-final { scan-assembler-times "setne" 1 } } */
+/* { dg-final { scan-assembler-times "sete" 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/cmpti2.c b/gcc/testsuite/gcc.target/i386/cmpti2.c
new file mode 100644
index 00000000000..ad9572901ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cmpti2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2" } */
+
+__int128 x;
+__int128 y;
+
+int eq() { return x == y; }
+int ne() { return x != y; }
+
+/* { dg-final { scan-assembler-times "xorq" 4 } } */
+/* { dg-final { scan-assembler-times "setne" 1 } } */
+/* { dg-final { scan-assembler-times "sete" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/cmpti3.c b/gcc/testsuite/gcc.target/i386/cmpti3.c
new file mode 100644
index 00000000000..302efd2ad59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/cmpti3.c
@@ -0,0 +1,13 @@
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2" } */
+
+__int128 x;
+int foo()
+{
+ __int128 t = 0x1234567890abcdefLL;
+ return x == t;
+}
+
+/* { dg-final { scan-assembler-times "movabsq" 1 } } */
+/* { dg-final { scan-assembler-times "xorq" 1 } } */
+/* { dg-final { scan-assembler-not "xorl" } } */