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 ThirtyTwoMinusImm : 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), (ThirtyTwoMinusImm uimm5:$shamt))>; +// shl/and can appear in the other order too. +def : Pat<(SLLIUWPat GPR:$rs1, uimm5:$shamt), + (SRLI (SLLI GPR:$rs1, 32), (ThirtyTwoMinusImm 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 @@ -77,13 +77,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()) 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 ;