diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -332,6 +332,12 @@ N->getValueType(0)); }]>; +// Return an immediate subtracted from 32. +def ImmSubFrom32 : SDNodeXFormgetTargetConstant(32 - N->getZExtValue(), SDLoc(N), + N->getValueType(0)); +}]>; + //===----------------------------------------------------------------------===// // Instruction Formats //===----------------------------------------------------------------------===// @@ -855,6 +861,13 @@ 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)>; @@ -1158,9 +1171,18 @@ /// 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 diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoB.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoB.td @@ -47,18 +47,12 @@ // Convert rotl immediate to a rotr immediate for XLen instructions. -def ImmROTL2R : SDNodeXFormgetXLen(); return CurDAG->getTargetConstant(XLen - N->getZExtValue(), SDLoc(N), N->getValueType(0)); }]>; -// Convert rotl immediate to a rotr immediate for W instructions. -def ImmROTL2RW : SDNodeXFormgetTargetConstant(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 +71,6 @@ 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 : ImmLeafis64Bit()) @@ -740,7 +727,7 @@ 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))>; } // We don't pattern-match sbclri[w], sbseti[w], sbinvi[w] because they are @@ -832,7 +819,7 @@ // 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 { @@ -974,7 +961,7 @@ 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 { @@ -1027,7 +1014,7 @@ 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 { diff --git a/llvm/test/CodeGen/RISCV/rv64Zba.ll b/llvm/test/CodeGen/RISCV/rv64Zba.ll --- a/llvm/test/CodeGen/RISCV/rv64Zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64Zba.ll @@ -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 @@ ; 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 @@ ; 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 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 @@ ; 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 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 @@ ; 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_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 ;