s390: Fix s390_valid_shift_count() for TI mode [PR118835]

Message ID 20250211171719.3433768-1-stefansf@gcc.gnu.org
State New
Headers
Series s390: Fix s390_valid_shift_count() for TI mode [PR118835] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap success Build passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap success Build passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Test passed

Commit Message

Stefan Schulze Frielinghaus Feb. 11, 2025, 5:17 p.m. UTC
  During combine we may end up with

(set (reg:DI 66 [ _6 ])
     (ashift:DI (reg:DI 72 [ x ])
                (subreg:QI (and:TI (reg:TI 67 [ _1 ])
                                   (const_wide_int 0x0aaaaaaaaaaaaaabf))
                           15)))

where the shift count operand does not trivially fit the scheme of
address operands.  Reject those operands, especially since
strip_address_mutations() expects expressions of the form
(and ... (const_int ...)) and fails for (and ... (const_wide_int ...)).

While on it, fix indentation of the if block.

gcc/ChangeLog:

	PR target/118835
	* config/s390/s390.cc (s390_valid_shift_count): Reject shift
	count operands which do not trivially fit the scheme of
	address operands.

gcc/testsuite/ChangeLog:

	* gcc.target/s390/pr118835.c: New test.
---
 Bootstrap and regtest are still running.  Assuming they finish without
 regressions and there are no further comments, I will push this.

 gcc/config/s390/s390.cc                  | 37 ++++++++++++++----------
 gcc/testsuite/gcc.target/s390/pr118835.c | 21 ++++++++++++++
 2 files changed, 43 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/pr118835.c
  

Patch

diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 1d96df49fea..c2636c54613 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -3510,26 +3510,33 @@  s390_valid_shift_count (rtx op, HOST_WIDE_INT implicit_mask)
 
   /* Check for an and with proper constant.  */
   if (GET_CODE (op) == AND)
-  {
-    rtx op1 = XEXP (op, 0);
-    rtx imm = XEXP (op, 1);
+    {
+      rtx op1 = XEXP (op, 0);
+      rtx imm = XEXP (op, 1);
 
-    if (GET_CODE (op1) == SUBREG && subreg_lowpart_p (op1))
-      op1 = XEXP (op1, 0);
+      if (GET_CODE (op1) == SUBREG && subreg_lowpart_p (op1))
+	op1 = XEXP (op1, 0);
 
-    if (!(register_operand (op1, GET_MODE (op1)) || GET_CODE (op1) == PLUS))
-      return false;
+      if (!(register_operand (op1, GET_MODE (op1)) || GET_CODE (op1) == PLUS))
+	return false;
 
-    if (!immediate_operand (imm, GET_MODE (imm)))
-      return false;
+      if (!immediate_operand (imm, GET_MODE (imm)))
+	return false;
 
-    HOST_WIDE_INT val = INTVAL (imm);
-    if (implicit_mask > 0
-	&& (val & implicit_mask) != implicit_mask)
-      return false;
+      /* Reject shift count operands which do not trivially fit the scheme of
+	 address operands.  Especially since strip_address_mutations() expects
+	 expressions of the form (and ... (const_int ...)) and fails for
+	 (and ... (const_wide_int ...)).  */
+      if (CONST_WIDE_INT_P (imm))
+	return false;
 
-    op = op1;
-  }
+      HOST_WIDE_INT val = INTVAL (imm);
+      if (implicit_mask > 0
+	  && (val & implicit_mask) != implicit_mask)
+	return false;
+
+      op = op1;
+    }
 
   /* Check the rest.  */
   return s390_decompose_addrstyle_without_index (op, NULL, NULL);
diff --git a/gcc/testsuite/gcc.target/s390/pr118835.c b/gcc/testsuite/gcc.target/s390/pr118835.c
new file mode 100644
index 00000000000..1ca6cd95543
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr118835.c
@@ -0,0 +1,21 @@ 
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2" } */
+
+/* During combine we may end up with patterns of the form
+
+   (set (reg:DI 66 [ _6 ])
+        (ashift:DI (reg:DI 72 [ x ])
+                   (subreg:QI (and:TI (reg:TI 67 [ _1 ])
+                                      (const_wide_int 0x0aaaaaaaaaaaaaabf))
+                              15)))
+
+   which should be rejected since the shift count does not trivially fit the
+   scheme of address operands.  */
+
+long
+test (long x, int y)
+{
+  __int128 z = 0xAAAAAAAAAAAAAABF;
+  z &= y;
+  return x << z;
+}