[RISCV] Add isel patterns to optimize slli.uw patterns without Zba extension.
authorCraig Topper <craig.topper@sifive.com>
Mon, 25 Jan 2021 23:59:25 +0000 (15:59 -0800)
committerCraig Topper <craig.topper@sifive.com>
Tue, 26 Jan 2021 00:12:08 +0000 (16:12 -0800)
This pattern can occur when an unsigned is used to index an array
on RV64.

Reviewed By: luismarques

Differential Revision: https://reviews.llvm.org/D95290

llvm/lib/Target/RISCV/RISCVInstrInfo.td
llvm/lib/Target/RISCV/RISCVInstrInfoB.td
llvm/test/CodeGen/RISCV/rv64Zba.ll

index 1b5683a..a07b589 100644 (file)
@@ -332,6 +332,19 @@ def ImmSub32 : SDNodeXForm<imm, [{
                                    N->getValueType(0));
 }]>;
 
+// Return an immediate subtracted from XLen.
+def ImmSubFromXLen : SDNodeXForm<imm, [{
+  uint64_t XLen = Subtarget->getXLen();
+  return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N),
+                                   N->getValueType(0));
+}]>;
+
+// Return an immediate subtracted from 32.
+def ImmSubFrom32 : SDNodeXForm<imm, [{
+  return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N),
+                                   N->getValueType(0));
+}]>;
+
 //===----------------------------------------------------------------------===//
 // Instruction Formats
 //===----------------------------------------------------------------------===//
@@ -855,6 +868,13 @@ def SRLIWPat : PatFrag<(ops node:$A, node:$B),
   return MatchSRLIW(N);
 }]>;
 
+// Check that it is a SLLIUW (Shift Logical Left Immediate Unsigned i32
+// on RV64). Also used to optimize the same sequence without SLLIUW.
+def SLLIUWPat : PatFrag<(ops node:$A, node:$B),
+                        (and (shl node:$A, node:$B), imm), [{
+  return MatchSLLIUW(N);
+}]>;
+
 /// Immediates
 
 def : Pat<(simm12:$imm), (ADDI X0, simm12:$imm)>;
@@ -1162,9 +1182,18 @@ def ADJCALLSTACKUP   : Pseudo<(outs), (ins i32imm:$amt1, i32imm:$amt2),
 
 /// RV64 patterns
 
-let Predicates = [IsRV64, NotHasStdExtZba] in
+let Predicates = [IsRV64, NotHasStdExtZba] in {
 def : Pat<(and GPR:$rs1, 0xffffffff), (SRLI (SLLI GPR:$rs1, 32), 32)>;
 
+// If we're shifting a 32-bit zero extended value left by 0-31 bits, use 2
+// shifts instead of 3. This can occur when unsigned is used to index an array.
+def : Pat<(shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt),
+          (SRLI (SLLI GPR:$rs1, 32), (ImmSubFrom32 uimm5:$shamt))>;
+// shl/and can appear in the other order too.
+def : Pat<(SLLIUWPat GPR:$rs1, uimm5:$shamt),
+          (SRLI (SLLI GPR:$rs1, 32), (ImmSubFrom32 uimm5:$shamt))>;
+}
+
 let Predicates = [IsRV64] in {
 
 /// sext and zext
index 501137a..1bc288b 100644 (file)
@@ -46,19 +46,6 @@ def shfl_uimm : Operand<XLenVT>, ImmLeaf<XLenVT, [{
 }
 
 
-// Convert rotl immediate to a rotr immediate for XLen instructions.
-def ImmROTL2R : SDNodeXForm<imm, [{
-  uint64_t XLen = Subtarget->getXLen();
-  return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N),
-                                   N->getValueType(0));
-}]>;
-
-// Convert rotl immediate to a rotr immediate for W instructions.
-def ImmROTL2RW : SDNodeXForm<imm, [{
-  return CurDAG->getTargetConstant(32 - N->getZExtValue(), SDLoc(N),
-                                   N->getValueType(0));
-}]>;
-
 // Check that it is a SLOI (Shift Left Ones Immediate).
 def SLOIPat : PatFrag<(ops node:$A, node:$B),
                       (or (shl node:$A, node:$B), imm), [{
@@ -77,13 +64,6 @@ def SROIWPat : PatFrag<(ops node:$A, node:$B),
   return MatchSROIW(N);
 }]>;
 
-// Check that it is a SLLIUW (Shift Logical Left Immediate Unsigned i32
-// on RV64).
-def SLLIUWPat : PatFrag<(ops node:$A, node:$B),
-                        (and (shl node:$A, node:$B), imm), [{
-  return MatchSLLIUW(N);
-}]>;
-
 // Checks if this mask has a single 0 bit and cannot be used with ANDI.
 def BCLRMask : ImmLeaf<XLenVT, [{
   if (Subtarget->is64Bit())
@@ -743,7 +723,7 @@ let Predicates = [HasStdExtZbbOrZbp] in {
 def : Pat<(rotr GPR:$rs1, uimmlog2xlen:$shamt),
           (RORI GPR:$rs1, uimmlog2xlen:$shamt)>;
 def : Pat<(rotl GPR:$rs1, uimmlog2xlen:$shamt),
-          (RORI GPR:$rs1, (ImmROTL2R uimmlog2xlen:$shamt))>;
+          (RORI GPR:$rs1, (ImmSubFromXLen uimmlog2xlen:$shamt))>;
 }
 
 def riscv_grevi    : SDNode<"RISCVISD::GREVI", SDTIntBinOp, []>;
@@ -829,7 +809,7 @@ def : Pat<(fshr GPR:$rs3, GPR:$rs1, uimmlog2xlen:$shamt),
 // We can use FSRI for fshl by immediate if we subtract the immediate from
 // XLen and swap the operands.
 def : Pat<(fshl GPR:$rs3, GPR:$rs1, uimmlog2xlen:$shamt),
-          (FSRI GPR:$rs1, GPR:$rs3, (ImmROTL2R uimmlog2xlen:$shamt))>;
+          (FSRI GPR:$rs1, GPR:$rs3, (ImmSubFromXLen uimmlog2xlen:$shamt))>;
 } // Predicates = [HasStdExtZbt]
 
 let Predicates = [HasStdExtZbb] in {
@@ -971,7 +951,7 @@ def : Pat<(riscv_rorw GPR:$rs1, GPR:$rs2),
 def : Pat<(riscv_rorw GPR:$rs1, uimm5:$rs2),
           (RORIW GPR:$rs1, uimm5:$rs2)>;
 def : Pat<(riscv_rolw GPR:$rs1, uimm5:$rs2),
-          (RORIW GPR:$rs1, (ImmROTL2RW uimm5:$rs2))>;
+          (RORIW GPR:$rs1, (ImmSubFrom32 uimm5:$rs2))>;
 } // Predicates = [HasStdExtZbbOrZbp, IsRV64]
 
 let Predicates = [HasStdExtZbs, IsRV64] in {
@@ -1024,7 +1004,7 @@ def : Pat<(riscv_fsrw GPR:$rs3, GPR:$rs1, GPR:$rs2),
 def : Pat<(riscv_fsrw GPR:$rs3, GPR:$rs1, uimm5:$shamt),
           (FSRIW GPR:$rs1, GPR:$rs3, uimm5:$shamt)>;
 def : Pat<(riscv_fslw GPR:$rs3, GPR:$rs1, uimm5:$shamt),
-          (FSRIW GPR:$rs1, GPR:$rs3, (ImmROTL2RW uimm5:$shamt))>;
+          (FSRIW GPR:$rs1, GPR:$rs3, (ImmSubFrom32 uimm5:$shamt))>;
 } // Predicates = [HasStdExtZbt, IsRV64]
 
 let Predicates = [HasStdExtZbb, IsRV64] in {
index 245de0d..9dcbaae 100644 (file)
@@ -9,11 +9,8 @@
 define i64 @slliuw(i64 %a) nounwind {
 ; RV64I-LABEL: slliuw:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    slli a0, a0, 1
-; RV64I-NEXT:    addi a1, zero, 1
-; RV64I-NEXT:    slli a1, a1, 33
-; RV64I-NEXT:    addi a1, a1, -2
-; RV64I-NEXT:    and a0, a0, a1
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 31
 ; RV64I-NEXT:    ret
 ;
 ; RV64IB-LABEL: slliuw:
@@ -34,8 +31,7 @@ define i128 @slliuw_2(i32 signext %0, i128* %1) {
 ; RV64I-LABEL: slliuw_2:
 ; RV64I:       # %bb.0:
 ; RV64I-NEXT:    slli a0, a0, 32
-; RV64I-NEXT:    srli a0, a0, 32
-; RV64I-NEXT:    slli a0, a0, 4
+; RV64I-NEXT:    srli a0, a0, 28
 ; RV64I-NEXT:    add a1, a1, a0
 ; RV64I-NEXT:    ld a0, 0(a1)
 ; RV64I-NEXT:    ld a1, 8(a1)
@@ -206,8 +202,7 @@ define signext i16 @sh1adduw(i32 signext %0, i16* %1) {
 ; RV64I-LABEL: sh1adduw:
 ; RV64I:       # %bb.0:
 ; RV64I-NEXT:    slli a0, a0, 32
-; RV64I-NEXT:    srli a0, a0, 32
-; RV64I-NEXT:    slli a0, a0, 1
+; RV64I-NEXT:    srli a0, a0, 31
 ; RV64I-NEXT:    add a0, a1, a0
 ; RV64I-NEXT:    lh a0, 0(a0)
 ; RV64I-NEXT:    ret
@@ -232,11 +227,8 @@ define signext i16 @sh1adduw(i32 signext %0, i16* %1) {
 define i64 @sh1adduw_2(i64 %0, i64 %1) {
 ; RV64I-LABEL: sh1adduw_2:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    slli a0, a0, 1
-; RV64I-NEXT:    addi a2, zero, 1
-; RV64I-NEXT:    slli a2, a2, 33
-; RV64I-NEXT:    addi a2, a2, -2
-; RV64I-NEXT:    and a0, a0, a2
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 31
 ; RV64I-NEXT:    add a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
@@ -259,8 +251,7 @@ define signext i32 @sh2adduw(i32 signext %0, i32* %1) {
 ; RV64I-LABEL: sh2adduw:
 ; RV64I:       # %bb.0:
 ; RV64I-NEXT:    slli a0, a0, 32
-; RV64I-NEXT:    srli a0, a0, 32
-; RV64I-NEXT:    slli a0, a0, 2
+; RV64I-NEXT:    srli a0, a0, 30
 ; RV64I-NEXT:    add a0, a1, a0
 ; RV64I-NEXT:    lw a0, 0(a0)
 ; RV64I-NEXT:    ret
@@ -285,11 +276,8 @@ define signext i32 @sh2adduw(i32 signext %0, i32* %1) {
 define i64 @sh2adduw_2(i64 %0, i64 %1) {
 ; RV64I-LABEL: sh2adduw_2:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    slli a0, a0, 2
-; RV64I-NEXT:    addi a2, zero, 1
-; RV64I-NEXT:    slli a2, a2, 34
-; RV64I-NEXT:    addi a2, a2, -4
-; RV64I-NEXT:    and a0, a0, a2
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 30
 ; RV64I-NEXT:    add a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
@@ -312,8 +300,7 @@ define i64 @sh3adduw(i32 signext %0, i64* %1) {
 ; RV64I-LABEL: sh3adduw:
 ; RV64I:       # %bb.0:
 ; RV64I-NEXT:    slli a0, a0, 32
-; RV64I-NEXT:    srli a0, a0, 32
-; RV64I-NEXT:    slli a0, a0, 3
+; RV64I-NEXT:    srli a0, a0, 29
 ; RV64I-NEXT:    add a0, a1, a0
 ; RV64I-NEXT:    ld a0, 0(a0)
 ; RV64I-NEXT:    ret
@@ -338,11 +325,8 @@ define i64 @sh3adduw(i32 signext %0, i64* %1) {
 define i64 @sh3adduw_2(i64 %0, i64 %1) {
 ; RV64I-LABEL: sh3adduw_2:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    slli a0, a0, 3
-; RV64I-NEXT:    addi a2, zero, 1
-; RV64I-NEXT:    slli a2, a2, 35
-; RV64I-NEXT:    addi a2, a2, -8
-; RV64I-NEXT:    and a0, a0, a2
+; RV64I-NEXT:    slli a0, a0, 32
+; RV64I-NEXT:    srli a0, a0, 29
 ; RV64I-NEXT:    add a0, a0, a1
 ; RV64I-NEXT:    ret
 ;