[PATCH, rtl] Fix PR/38554

Adam Nemet anemet@caviumnetworks.com
Thu Jan 15 09:15:00 GMT 2009


This was initially reported for MIPS but I believe the testcase below should
ICE on any SHIFT_COUNT_TRUNCATED target.

Inside expand_shift, amount is:

(int) VIEW_CONVERT_EXPR<const unsigned int>(D.1243)

It gets expanded into:

(subreg:SI (reg:SF 200 [ D.1243 ]) 0)

But then the subreg is removed if SHIFT_COUNT_TRUNCATED.  I think the logic is
that a lowpart subreg operation is redundant if the HW also performs a
truncation.

Later we fail an assert in convert_move while trying to convert the value from
SF to SI mode.

My fix only allows this optimization if the subreg'ed value is also integral,
IOW the subreg is not used to cast the value.  According to RichardG the above
tree expression to access a union is new in 4.4 hence this regression.

Bootstrapped and tested on mips64octeon-linux.

OK to install?

Adam

	PR target/38554
	* expmed.c (expand_shift): With SHIFT_COUNT_TRUNCATED, don't lift
	the subreg from a lowpart subreg if it is also casting the value.

testsuite/
	PR target/38554
	* gcc.c-torture/compile/pr38554.c: New test.

Index: expmed.c
===================================================================
--- expmed.c	(revision 143288)
+++ expmed.c	(working copy)
@@ -2136,7 +2136,8 @@ expand_shift (enum tree_code code, enum 
 	op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
 		       % GET_MODE_BITSIZE (mode));
       else if (GET_CODE (op1) == SUBREG
-	       && subreg_lowpart_p (op1))
+	       && subreg_lowpart_p (op1)
+	       && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (op1))))
 	op1 = SUBREG_REG (op1);
     }
 
Index: testsuite/gcc.c-torture/compile/pr38554.c
===================================================================
--- testsuite/gcc.c-torture/compile/pr38554.c	(revision 0)
+++ testsuite/gcc.c-torture/compile/pr38554.c	(revision 0)
@@ -0,0 +1,45 @@
+typedef unsigned long sample;
+struct pam
+{
+  sample maxval;
+};
+typedef sample *tuple;
+enum function
+  {
+    FN_MULTIPLY, FN_DIVIDE, FN_ADD, FN_SUBTRACT, FN_MIN, FN_MAX, FN_AND, FN_OR,
+    FN_XOR, FN_NOT, FN_SHIFTLEFT, FN_SHIFTRIGHT
+  };
+struct cmdlineInfo
+{
+  enum function function;
+  union
+  {
+    float divisor;
+    unsigned int shiftCount;
+  }
+    u;
+};
+applyFunction (struct cmdlineInfo const cmdline, struct pam const inpam,
+               struct pam const outpam, tuple * const inputRow,
+               tuple * const outputRow)
+{
+  float const oneOverDivisor = 1 / cmdline.u.divisor;
+  int col;
+  {
+    int plane;
+    {
+      sample const inSample = inputRow[col][plane];
+      sample outSample;
+      switch (cmdline.function)
+        {
+        case FN_DIVIDE:
+          outSample = ((unsigned int) ((inSample * oneOverDivisor) + 0.5));
+          break;
+        case FN_SHIFTLEFT:
+          outSample = (inSample << cmdline.u.shiftCount) & outpam.maxval;
+        }
+      outputRow[col][plane] =
+        ((outpam.maxval) < (outSample) ? (outpam.maxval) : (outSample));
+    }
+  }
+}



More information about the Gcc-patches mailing list