diff mbox series

[committed,rtl-optimization/87761] Partial fix by improving ability to generate exts instructions

Message ID aa68ee2b-d030-a76f-8fce-af1b213b4735@redhat.com
State New
Headers show
Series [committed,rtl-optimization/87761] Partial fix by improving ability to generate exts instructions | expand

Commit Message

Jeff Law Feb. 22, 2019, 4:39 p.m. UTC
This mips.md fixes part of 87761.  Specifically the failures for
octeon-exts-3.

There's roughly two ways to address the octeon-exts-3 issue.

One is to recognize that (set (dest) (ashiftrt (truncate (shift ...))))
is really just a bitfield extraction.  This is fairly easily done in
make_field_assignment.   The field starts at the outer shift constant
less the inner shift constant.  Its length is the size of the outer mode
less the outer shift constant.  The outer shift constant must be >= the
inner shift constant.

I originally preferred this approach as I expected it be a fairly
generic improvement.  As it turns out generation of the truncate in this
context is really only going to happen on targets that do not have noop
truncation -- mips, gcn, spe and one other minor target IIRC from my
investigations.  It's really a pretty narrow set of targets.

Additionally, even within that target set it's fairly difficult to
trigger outside the test -- even with a toolchain configured with all
the right defaults I only see a few generated in libgcc -- and it's
likely just one instance appearing across multilibs.

With such a narrow improvement profile I figured it was just safer to
attack in mips.md.  That way if by some chance I mucked it up it would
only affect mips.  So that's precisely what this patch does  with a new
mips.md pattern.

I've run the gcc.target/mips/mips.exp tests before/after, the only
changes are that octeon-exts-3.c now pass (using a compiler that
defaulted to abi=64).  I've also built mips64-linux-gnu (compiler,
glibc, kernel) and mips64el-linux-gnu (compiler, glibc, kernel) and
bootstrapped mips32r2-linux-gnu.  I doubt those builds actually test
this code though since I think they use the wrong ABI to trigger this
pattern.


I'm installing this on the trunk momentarily.

Jeff
diff mbox series

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 42ed0dca5b0..edaf84416c2 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  Martin Sebor  <msebor@redhat.com>
 
 	PR c/89425
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")])
 
 ;;
 ;;  ....................