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 --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 <l...@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 <mse...@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")]) ;; ;; ....................