summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2019-02-22 09:38:43 -0700
committerJeff Law <law@gcc.gnu.org>2019-02-22 09:38:43 -0700
commitcfed471a5612a925d55dae4085aa10d230bf4494 (patch)
treed087a0bc8ca4e34b63b824a05c0c50ff43fa715e
parent341fca1b4982c93a7c6cce90b0e0f84f92a35146 (diff)
downloadgcc-cfed471a5612a925d55dae4085aa10d230bf4494.tar.gz
re PR rtl-optimization/87761 ([MIPS] New FAIL: gcc.target/mips/fix-r4000-10.c -O1 start with r265398)
PR rtl-optimization/87761 * config/mips/mips.md: Add new combiner pattern to recognize a bitfield extraction using (ashiftrt (truncate (ashift (...)))). From-SVN: r269123
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/mips/mips.md41
2 files changed, 47 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8b283d5014b..64dcda2560f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2019-02-22 Jeff Law <law@redhat.com>
+
+ PR rtl-optimization/87761
+ * config/mips/mips.md: Add new combiner pattern to recognize
+ a bitfield extraction using (ashiftrt (truncate (ashift (...)))).
+
2019-02-22 Matthew Malcomson <matthew.malcomson@arm.com>
PR target/89324
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 25e0df218be..2ae1f7e0440 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -3502,6 +3502,47 @@
"exts\t%0,%1,%2,31"
[(set_attr "type" "arith")
(set_attr "mode" "<MODE>")])
+
+;; This could likely be generalized for any SUBDI mode, and any right
+;; shift, but AFAICT this is used so rarely it is not worth the additional
+;; complexity.
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ashiftrt:SI
+ (truncate:SI
+ (ashift:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "const_arith_operand" "")))
+ (match_operand:DI 3 "const_arith_operand" "")))]
+ "(ISA_HAS_EXTS && TARGET_64BIT
+ && UINTVAL (operands[2]) < 32 && UINTVAL (operands[3]) < 32
+ && UINTVAL (operands[3]) >= UINTVAL (operands[2]))"
+ {
+ rtx xoperands[4];
+ xoperands[0] = operands[0];
+ xoperands[1] = operands[1];
+
+ /* The length of the field is the size of the outer mode less the outer
+ shift constant. We fix the outer mode as SImode for simplicity. */
+ unsigned int right_shift = INTVAL (operands[3]);
+ xoperands[3] = GEN_INT (32 - right_shift);
+
+ /* The field starts at the outer shift constant less the inner shift
+ constant. */
+ unsigned int left_shift = INTVAL (operands[2]);
+ xoperands[2] = GEN_INT (right_shift - left_shift);
+
+ /* Sanity checks. These constraints are taken from the MIPS ISA
+ manual. */
+ gcc_assert (INTVAL (xoperands[2]) >= 0 && INTVAL (xoperands[2]) < 32);
+ gcc_assert (INTVAL (xoperands[3]) > 0 && INTVAL (xoperands[3]) <= 32);
+ gcc_assert (INTVAL (xoperands[2]) + INTVAL (xoperands[3]) > 0
+ && INTVAL (xoperands[2]) + INTVAL (xoperands[3]) <= 32);
+
+ output_asm_insn ("exts\t%0,%1,%2,%m3", xoperands);
+ return "";
+ }
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
;;
;; ....................