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
//===----------------------------------------------------------------------===//
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)>;
/// 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
}
-// 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), [{
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())
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, []>;
// 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 {
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 {
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 {
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:
; 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)
; 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
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
;
; 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
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
;
; 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
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
;