[gcc r16-815] i386: Extend *cmp<mode>_minus_1 optimizations also to plus with CONST_INT [PR120360]
Jakub Jelinek
jakub@gcc.gnu.org
Thu May 22 07:11:20 GMT 2025
https://gcc.gnu.org/g:5f4e794fd3efb0e44a6b5afdead95033df69c41b
commit r16-815-g5f4e794fd3efb0e44a6b5afdead95033df69c41b
Author: Jakub Jelinek <jakub@redhat.com>
Date: Thu May 22 09:09:48 2025 +0200
i386: Extend *cmp<mode>_minus_1 optimizations also to plus with CONST_INT [PR120360]
As mentioned by Linus, we can't optimize comparison of otherwise unused
result of plus with CONST_INT second operand, compared against zero.
This can be done using just cmp instruction with negated constant and say
js/jns/je/jne etc. conditional jumps (or setcc).
We already have *cmp<mode>_minus_1 instruction which handles it when
(as shown in foo in the testcase) the IL has MINUS rather than PLUS,
but for constants except for the minimum value the canonical form is
with PLUS.
The following patch adds a new pattern and predicate to handle this.
2025-05-22 Jakub Jelinek <jakub@redhat.com>
PR target/120360
* config/i386/predicates.md (x86_64_neg_const_int_operand): New
predicate.
* config/i386/i386.md (*cmp<mode>_plus_1): New pattern.
* gcc.target/i386/pr120360.c: New test.
Diff:
---
gcc/config/i386/i386.md | 14 +++++++++++++
gcc/config/i386/predicates.md | 17 +++++++++++++++
gcc/testsuite/gcc.target/i386/pr120360.c | 36 ++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+)
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index af4f12956251..b7a18d583da3 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1599,6 +1599,20 @@
[(set_attr "type" "icmp")
(set_attr "mode" "<MODE>")])
+(define_insn "*cmp<mode>_plus_1"
+ [(set (reg FLAGS_REG)
+ (compare
+ (plus:SWI (match_operand:SWI 0 "nonimmediate_operand" "<r>m")
+ (match_operand:SWI 1 "x86_64_neg_const_int_operand" "n"))
+ (const_int 0)))]
+ "ix86_match_ccmode (insn, CCGOCmode)"
+{
+ operands[1] = gen_int_mode (-INTVAL (operands[1]), <MODE>mode);
+ return "cmp{<imodesuffix>}\t{%1, %0|%0, %1}";
+}
+ [(set_attr "type" "icmp")
+ (set_attr "mode" "<MODE>")])
+
(define_insn "*cmpqi_ext<mode>_1"
[(set (reg FLAGS_REG)
(compare
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 10ed6a5de56e..1bd63b2367e1 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -393,6 +393,23 @@
return false;
})
+;; Return true if VALUE is a constant integer whose negation satisfies
+;; x86_64_immediate_operand.
+(define_predicate "x86_64_neg_const_int_operand"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT val = -UINTVAL (op);
+ if (mode == DImode && trunc_int_for_mode (val, SImode) != val)
+ return false;
+ if (flag_cf_protection & CF_BRANCH)
+ {
+ unsigned HOST_WIDE_INT endbr = TARGET_64BIT ? 0xfa1e0ff3 : 0xfb1e0ff3;
+ if ((val & HOST_WIDE_INT_C (0xffffffff)) == endbr)
+ return false;
+ }
+ return true;
+})
+
;; Return true if VALUE is a constant integer whose low and high words satisfy
;; x86_64_immediate_operand.
(define_predicate "x86_64_hilo_int_operand"
diff --git a/gcc/testsuite/gcc.target/i386/pr120360.c b/gcc/testsuite/gcc.target/i386/pr120360.c
new file mode 100644
index 000000000000..69c510ef004d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr120360.c
@@ -0,0 +1,36 @@
+/* PR target/120360 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-stack-protector -masm=att" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+/* { dg-final { scan-assembler-times "\tjn*s\t" 3 } } */
+/* { dg-final { scan-assembler-times "\tcmp\[lq]\t%" 1 } } */
+/* { dg-final { scan-assembler-times "\tcmp\[lq]\t\\\$-1234," 1 } } */
+/* { dg-final { scan-assembler-times "\tcmp\[lq]\t\\\$2345," 1 } } */
+/* { dg-final { scan-assembler-not "\tadd\[lq]\t" { target { ! *-*-darwin* } } } } */
+/* { dg-final { scan-assembler-not "\tsub\[lq]\t" { target { ! *-*-darwin* } } } } */
+
+void qux (unsigned long);
+
+void
+foo (unsigned long x, unsigned long y)
+{
+ unsigned long z = x - y;
+ if ((long) z < 0)
+ qux (x);
+}
+
+void
+bar (unsigned long x)
+{
+ unsigned long z = x + 1234;
+ if ((long) z < 0)
+ qux (x);
+}
+
+void
+baz (unsigned long x)
+{
+ unsigned long z = x - 2345;
+ if ((long) z < 0)
+ qux (x);
+}
More information about the Gcc-cvs
mailing list