simplify-rtx: Handle truncate of extract
authorSegher Boessenkool <segher@kernel.crashing.org>
Tue, 29 Nov 2016 01:48:30 +0000 (02:48 +0100)
committerSegher Boessenkool <segher@gcc.gnu.org>
Tue, 29 Nov 2016 01:48:30 +0000 (02:48 +0100)
simplify_truncation changes the truncation of many operations into
the operation on the truncation.  This patch makes this code also
handle extracts.

* simplify-rtx.c (simplify_truncation): Handle truncate of zero_extract
and sign_extract.

From-SVN: r242946

gcc/ChangeLog
gcc/simplify-rtx.c

index 5ce50b04f55f75a71998d71df3f33e64db95d308..900f9b355d74ca1a49b2fbcb42ba2fd3957edae0 100644 (file)
@@ -1,3 +1,8 @@
+2016-11-28  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       * simplify-rtx.c (simplify_truncation): Handle truncate of zero_extract
+       and sign_extract.
+
 2016-11-28  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (*and<mode>_1): Merge insn pattern from
index 83fb37d853524ca6206ea2e9a2899d66394ede60..7778db55a24a37aaf6185457f40cbee847b442b3 100644 (file)
@@ -747,6 +747,36 @@ simplify_truncation (machine_mode mode, rtx op,
        }
     }
 
+  /* Turn (truncate:M1 (*_extract:M2 (reg:M2) (len) (pos))) into
+     (*_extract:M1 (truncate:M1 (reg:M2)) (len) (pos')) if possible without
+     changing len.  */
+  if ((GET_CODE (op) == ZERO_EXTRACT || GET_CODE (op) == SIGN_EXTRACT)
+      && REG_P (XEXP (op, 0))
+      && CONST_INT_P (XEXP (op, 1))
+      && CONST_INT_P (XEXP (op, 2)))
+    {
+      rtx op0 = XEXP (op, 0);
+      unsigned HOST_WIDE_INT len = UINTVAL (XEXP (op, 1));
+      unsigned HOST_WIDE_INT pos = UINTVAL (XEXP (op, 2));
+      if (BITS_BIG_ENDIAN && pos >= op_precision - precision)
+       {
+         op0 = simplify_gen_unary (TRUNCATE, mode, op0, GET_MODE (op0));
+         if (op0)
+           {
+             pos -= op_precision - precision;
+             return simplify_gen_ternary (GET_CODE (op), mode, mode, op0,
+                                          XEXP (op, 1), GEN_INT (pos));
+           }
+       }
+      else if (!BITS_BIG_ENDIAN && precision >= len + pos)
+       {
+         op0 = simplify_gen_unary (TRUNCATE, mode, op0, GET_MODE (op0));
+         if (op0)
+           return simplify_gen_ternary (GET_CODE (op), mode, mode, op0,
+                                        XEXP (op, 1), XEXP (op, 2));
+       }
+    }
+
   /* Recognize a word extraction from a multi-word subreg.  */
   if ((GET_CODE (op) == LSHIFTRT
        || GET_CODE (op) == ASHIFTRT)