diff options
author | Jakub Jelinek <jakub@redhat.com> | 2025-04-17 10:57:18 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2025-04-17 10:57:18 +0200 |
commit | 22fe83d6fc9f59311241c981bcad58b61e2056d4 (patch) | |
tree | ad63638cbd28b9f0f440cd8b7d65878a053a2c7e | |
parent | 843b273c6851b71407b116584982b0389be4d6fd (diff) | |
download | gcc-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.md | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.target/s390/pr119834.C | 76 |
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 (); } |