aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-04-17 10:57:18 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2025-04-17 10:57:18 +0200
commit22fe83d6fc9f59311241c981bcad58b61e2056d4 (patch)
treead63638cbd28b9f0f440cd8b7d65878a053a2c7e
parent843b273c6851b71407b116584982b0389be4d6fd (diff)
downloadgcc-22fe83d6fc9f59311241c981bcad58b61e2056d4.zip
gcc-22fe83d6fc9f59311241c981bcad58b61e2056d4.tar.gz
gcc-22fe83d6fc9f59311241c981bcad58b61e2056d4.tar.bz2
s390: Use match_scratch instead of scratch in define_split [PR119834]
The following testcase ICEs since r15-1579 (addition of late combiner), because *clrmem_short can't be split. The problem is that the define_insn uses (use (match_operand 1 "nonmemory_operand" "n,a,a,a")) (use (match_operand 2 "immediate_operand" "X,R,X,X")) (clobber (match_scratch:P 3 "=X,X,X,&a")) and define_split assumed that if operands[1] is const_int_operand, match_scratch will be always scratch, and it will be reg only if it was the last alternative where operands[1] is a reg. The pattern doesn't guarantee it though, of course RA will not try to uselessly assign a reg there if it is not needed, but during RA on the testcase below we match the last alternative, but then comes late combiner and propagates const_int 3 into operands[1]. And that matches fine, match_scratch matches either scratch or reg and the constraint in that case is X for the first variant, so still just fine. But we won't split that because the splitters only expect scratch. The following patch fixes it by using match_scratch instead of scratch, so that it accepts either. 2025-04-17 Jakub Jelinek <jakub@redhat.com> PR target/119834 * config/s390/s390.md (define_split after *cpymem_short): Use (clobber (match_scratch N)) instead of (clobber (scratch)). Use (match_dup 4) and operands[4] instead of (match_dup 3) and operands[3] in the last of those. (define_split after *clrmem_short): Use (clobber (match_scratch N)) instead of (clobber (scratch)). (define_split after *cmpmem_short): Likewise. * g++.target/s390/pr119834.C: New test.
-rw-r--r--gcc/config/s390/s390.md22
-rw-r--r--gcc/testsuite/g++.target/s390/pr119834.C76
2 files changed, 87 insertions, 11 deletions
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 874974a..05b9da6 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -3597,7 +3597,7 @@
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "const_int_operand" ""))
(use (match_operand 3 "immediate_operand" ""))
- (clobber (scratch))]
+ (clobber (match_scratch 4))]
"reload_completed"
[(parallel
[(set (match_dup 0) (match_dup 1))
@@ -3609,7 +3609,7 @@
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "register_operand" ""))
(use (match_operand 3 "memory_operand" ""))
- (clobber (scratch))]
+ (clobber (match_scratch 4))]
"reload_completed"
[(parallel
[(unspec [(match_dup 2) (match_dup 3)
@@ -3623,14 +3623,14 @@
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
- (clobber (scratch))]
+ (clobber (match_scratch 3))]
"TARGET_Z10 && reload_completed"
[(parallel
[(unspec [(match_dup 2) (const_int 0)
- (label_ref (match_dup 3))] UNSPEC_EXECUTE)
+ (label_ref (match_dup 4))] UNSPEC_EXECUTE)
(set (match_dup 0) (match_dup 1))
(use (const_int 1))])]
- "operands[3] = gen_label_rtx ();")
+ "operands[4] = gen_label_rtx ();")
(define_split
[(set (match_operand:BLK 0 "memory_operand" "")
@@ -3852,7 +3852,7 @@
(const_int 0))
(use (match_operand 1 "const_int_operand" ""))
(use (match_operand 2 "immediate_operand" ""))
- (clobber (scratch))
+ (clobber (match_scratch 3))
(clobber (reg:CC CC_REGNUM))]
"reload_completed"
[(parallel
@@ -3866,7 +3866,7 @@
(const_int 0))
(use (match_operand 1 "register_operand" ""))
(use (match_operand 2 "memory_operand" ""))
- (clobber (scratch))
+ (clobber (match_scratch 3))
(clobber (reg:CC CC_REGNUM))]
"reload_completed"
[(parallel
@@ -3882,7 +3882,7 @@
(const_int 0))
(use (match_operand 1 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
- (clobber (scratch))
+ (clobber (match_scratch 2))
(clobber (reg:CC CC_REGNUM))]
"TARGET_Z10 && reload_completed"
[(parallel
@@ -4047,7 +4047,7 @@
(match_operand:BLK 1 "memory_operand" "")))
(use (match_operand 2 "const_int_operand" ""))
(use (match_operand 3 "immediate_operand" ""))
- (clobber (scratch))]
+ (clobber (match_scratch 4))]
"reload_completed"
[(parallel
[(set (reg:CCU CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
@@ -4060,7 +4060,7 @@
(match_operand:BLK 1 "memory_operand" "")))
(use (match_operand 2 "register_operand" ""))
(use (match_operand 3 "memory_operand" ""))
- (clobber (scratch))]
+ (clobber (match_scratch 4))]
"reload_completed"
[(parallel
[(unspec [(match_dup 2) (match_dup 3)
@@ -4075,7 +4075,7 @@
(match_operand:BLK 1 "memory_operand" "")))
(use (match_operand 2 "register_operand" ""))
(use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
- (clobber (scratch))]
+ (clobber (match_scratch 3))]
"TARGET_Z10 && reload_completed"
[(parallel
[(unspec [(match_dup 2) (const_int 0)
diff --git a/gcc/testsuite/g++.target/s390/pr119834.C b/gcc/testsuite/g++.target/s390/pr119834.C
new file mode 100644
index 0000000..66c0a69
--- /dev/null
+++ b/gcc/testsuite/g++.target/s390/pr119834.C
@@ -0,0 +1,76 @@
+// PR target/119834
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -march=z900" }
+
+int *a;
+struct A;
+struct B {
+ A begin ();
+ A end ();
+ operator bool * ();
+ void operator++ ();
+};
+template <typename T>
+auto operator| (int, T x) -> decltype (x (0));
+struct A : B { bool a; };
+struct C { A operator () (int); };
+enum D {} d;
+int e;
+void foo ();
+struct E {
+ template <typename T>
+ T *garply ()
+ {
+ if (d)
+ return 0;
+ if (e)
+ foo ();
+ return reinterpret_cast<T *> (f);
+ }
+ template <typename>
+ void bar (long x, bool)
+ {
+ if (&g - f)
+ __builtin_memset (a, 0, x);
+ f += x;
+ }
+ template <typename T>
+ T *baz (T *x, long y, bool z = true)
+ {
+ if (d)
+ return nullptr;
+ bar<T> ((char *)x + y - f, z);
+ return x;
+ }
+ template <typename T>
+ void qux (T x) { baz (x, x->j); }
+ char *f, g;
+} *h;
+struct F {
+ template <typename T>
+ int corge (T x) { x.freddy (this); return 0; }
+ template <typename T>
+ int boo (T x) { corge (x); return 0; }
+} i;
+template <typename T>
+struct G {
+ template <typename U> friend T operator+ (U, G);
+ template <typename U>
+ void waldo (F *x, G y, U z) { x->boo (z + y); }
+ template <typename... Ts>
+ void plugh (E *y, Ts... z) { T *x = y->garply<T> (); x->thud (y, z...); }
+};
+template <typename T> using H = G<T>;
+struct I {
+ static constexpr unsigned j = 2;
+ void thud (E *x, A y) { x->qux (this); for (auto g : y) ; }
+};
+H<I> k;
+struct J {
+ void freddy (F *) { C a; auto b = 0 | a; k.plugh (h, b); }
+};
+H<J> l;
+struct K {
+ void freddy () { l.waldo (&i, l, this); }
+};
+void grault () { K m; m.freddy (); }