Skip to content
Merged
45 changes: 40 additions & 5 deletions llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,11 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
.lower();

getActionDefinitionsBuilder({G_SHL, G_ASHR, G_LSHR})
.legalFor({{s32, s32}, {sXLen, sXLen}})
.legalFor({{sXLen, sXLen}})
.customFor(ST.is64Bit(), {{s32, s32}})
.widenScalarToNextPow2(0)
.clampScalar(1, s32, sXLen)
.clampScalar(0, s32, sXLen)
.minScalarSameAs(1, 0)
.maxScalarSameAs(1, 0);
.clampScalar(1, sXLen, sXLen)
.clampScalar(0, sXLen, sXLen);

auto &ExtActions =
getActionDefinitionsBuilder({G_ZEXT, G_SEXT, G_ANYEXT})
Expand Down Expand Up @@ -1166,6 +1165,12 @@ static unsigned getRISCVWOpcode(unsigned Opcode) {
switch (Opcode) {
default:
llvm_unreachable("Unexpected opcode");
case TargetOpcode::G_ASHR:
return RISCV::G_SRAW;
case TargetOpcode::G_LSHR:
return RISCV::G_SRLW;
case TargetOpcode::G_SHL:
return RISCV::G_SLLW;
case TargetOpcode::G_SDIV:
return RISCV::G_DIVW;
case TargetOpcode::G_UDIV:
Expand Down Expand Up @@ -1223,6 +1228,36 @@ bool RISCVLegalizerInfo::legalizeCustom(
return Helper.lower(MI, 0, /* Unused hint type */ LLT()) ==
LegalizerHelper::Legalized;
}
case TargetOpcode::G_ASHR:
case TargetOpcode::G_LSHR:
case TargetOpcode::G_SHL: {
Register AmtReg = MI.getOperand(2).getReg();
auto VRegAndVal = getIConstantVRegValWithLookThrough(AmtReg, MRI);
if (VRegAndVal) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auto VRegAndVal = getIConstantVRegValWithLookThrough(AmtReg, MRI);
if (VRegAndVal) {
if (getIConstantVRegValWithLookThrough(AmtReg, MRI)) {

// We don't need a custom node for shift by constant. Just widen the
// source and the shift amount.
unsigned ExtOpc = TargetOpcode::G_ANYEXT;
if (MI.getOpcode() == TargetOpcode::G_ASHR)
ExtOpc = TargetOpcode::G_SEXT;
else if (MI.getOpcode() == TargetOpcode::G_LSHR)
ExtOpc = TargetOpcode::G_ZEXT;

Helper.Observer.changingInstr(MI);
Helper.widenScalarSrc(MI, sXLen, 1, ExtOpc);
Helper.widenScalarSrc(MI, sXLen, 2, TargetOpcode::G_ZEXT);
Helper.widenScalarDst(MI, sXLen);
Helper.Observer.changedInstr(MI);
return true;
}

Helper.Observer.changingInstr(MI);
Helper.widenScalarSrc(MI, sXLen, 1, TargetOpcode::G_ANYEXT);
Helper.widenScalarSrc(MI, sXLen, 2, TargetOpcode::G_ANYEXT);
Helper.widenScalarDst(MI, sXLen);
MI.setDesc(MIRBuilder.getTII().get(getRISCVWOpcode(MI.getOpcode())));
Helper.Observer.changedInstr(MI);
return true;
}
case TargetOpcode::G_SDIV:
case TargetOpcode::G_UDIV:
case TargetOpcode::G_UREM:
Expand Down
22 changes: 6 additions & 16 deletions llvm/lib/Target/RISCV/RISCVGISel.td
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ def : LdPat<load, LD, PtrVT>;
def : StPat<store, SD, GPR, PtrVT>;
}

let Predicates = [IsRV64] in {
// FIXME: Temporary until i32->i64 zext is no longer legal.
def : Pat <(srl (zext GPR:$rs1), uimm5:$shamt),
(SRLIW GPR:$rs1, uimm5:$shamt)>;
}

//===----------------------------------------------------------------------===//
// RV64 i32 patterns not used by SelectionDAG
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -201,9 +207,6 @@ def : PatGprGpr<sub, SUBW, i32, i32>;
def : PatGprGpr<and, AND, i32, i32>;
def : PatGprGpr<or, OR, i32, i32>;
def : PatGprGpr<xor, XOR, i32, i32>;
def : PatGprGpr<shl, SLLW, i32, i32>;
def : PatGprGpr<srl, SRLW, i32, i32>;
def : PatGprGpr<sra, SRAW, i32, i32>;

def : Pat<(i32 (add GPR:$rs1, simm12i32:$imm)),
(ADDIW GPR:$rs1, (i64 (as_i64imm $imm)))>;
Expand All @@ -214,13 +217,6 @@ def : Pat<(i32 (or GPR:$rs1, simm12i32:$imm)),
def : Pat<(i32 (xor GPR:$rs1, simm12i32:$imm)),
(XORI GPR:$rs1, (i64 (as_i64imm $imm)))>;

def : Pat<(i32 (shl GPR:$rs1, uimm5i32:$imm)),
(SLLIW GPR:$rs1, (i64 (as_i64imm $imm)))>;
def : Pat<(i32 (srl GPR:$rs1, uimm5i32:$imm)),
(SRLIW GPR:$rs1, (i64 (as_i64imm $imm)))>;
def : Pat<(i32 (sra GPR:$rs1, uimm5i32:$imm)),
(SRAIW GPR:$rs1, (i64 (as_i64imm $imm)))>;

def : Pat<(i32 (and GPR:$rs, TrailingOnesMask:$mask)),
(SRLI (i32 (SLLI $rs, (i64 (XLenSubTrailingOnes $mask)))),
(i64 (XLenSubTrailingOnes $mask)))>;
Expand Down Expand Up @@ -270,10 +266,4 @@ def : Pat<(shl (i64 (zext GPR:$rs1)), uimm5:$shamt),
def : Pat<(i64 (add_like_non_imm12 (zext GPR:$rs1), GPR:$rs2)),
(ADD_UW GPR:$rs1, GPR:$rs2)>;
def : Pat<(zext GPR:$src), (ADD_UW GPR:$src, (XLenVT X0))>;

foreach i = {1,2,3} in {
defvar shxadd = !cast<Instruction>("SH"#i#"ADD");
def : Pat<(i32 (add_like_non_imm12 (shl GPR:$rs1, (i32 i)), GPR:$rs2)),
(shxadd GPR:$rs1, GPR:$rs2)>;
}
}
24 changes: 24 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrGISel.td
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,30 @@ class RISCVGenericInstruction : GenericInstruction {
let Namespace = "RISCV";
}

// Pseudo equivalent to a RISCVISD::SRAW.
def G_SRAW : RISCVGenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1, type0:$src2);
let hasSideEffects = false;
}
def : GINodeEquiv<G_SRAW, riscv_sraw>;

// Pseudo equivalent to a RISCVISD::SRLW.
def G_SRLW : RISCVGenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1, type0:$src2);
let hasSideEffects = false;
}
def : GINodeEquiv<G_SRLW, riscv_srlw>;

// Pseudo equivalent to a RISCVISD::SLLW.
def G_SLLW : RISCVGenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins type0:$src1, type0:$src2);
let hasSideEffects = false;
}
def : GINodeEquiv<G_SLLW, riscv_sllw>;

// Pseudo equivalent to a RISCVISD::DIVW.
def G_DIVW : RISCVGenericInstruction {
let OutOperandList = (outs type0:$dst);
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip.ll
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ define i32 @slli_i32(i32 %a) {
;
; RV64IM-LABEL: slli_i32:
; RV64IM: # %bb.0: # %entry
; RV64IM-NEXT: slliw a0, a0, 11
; RV64IM-NEXT: slli a0, a0, 11
; RV64IM-NEXT: ret
entry:
%0 = shl i32 %a, 11
Expand Down
62 changes: 31 additions & 31 deletions llvm/test/CodeGen/RISCV/GlobalISel/bitmanip.ll
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ define i2 @bitreverse_i2(i2 %x) {
; RV64-NEXT: slli a1, a0, 1
; RV64-NEXT: andi a1, a1, 2
; RV64-NEXT: andi a0, a0, 3
; RV64-NEXT: srliw a0, a0, 1
; RV64-NEXT: srli a0, a0, 1
; RV64-NEXT: or a0, a1, a0
; RV64-NEXT: ret
%rev = call i2 @llvm.bitreverse.i2(i2 %x)
Expand All @@ -43,7 +43,7 @@ define i3 @bitreverse_i3(i3 %x) {
; RV64-NEXT: andi a0, a0, 7
; RV64-NEXT: andi a2, a0, 2
; RV64-NEXT: or a1, a1, a2
; RV64-NEXT: srliw a0, a0, 2
; RV64-NEXT: srli a0, a0, 2
; RV64-NEXT: or a0, a1, a0
; RV64-NEXT: ret
%rev = call i3 @llvm.bitreverse.i3(i3 %x)
Expand Down Expand Up @@ -74,10 +74,10 @@ define i4 @bitreverse_i4(i4 %x) {
; RV64-NEXT: andi a2, a2, 4
; RV64-NEXT: or a1, a1, a2
; RV64-NEXT: andi a0, a0, 15
; RV64-NEXT: srliw a2, a0, 1
; RV64-NEXT: srli a2, a0, 1
; RV64-NEXT: andi a2, a2, 2
; RV64-NEXT: or a1, a1, a2
; RV64-NEXT: srliw a0, a0, 3
; RV64-NEXT: srli a0, a0, 3
; RV64-NEXT: or a0, a1, a0
; RV64-NEXT: ret
%rev = call i4 @llvm.bitreverse.i4(i4 %x)
Expand Down Expand Up @@ -121,13 +121,13 @@ define i7 @bitreverse_i7(i7 %x) {
; RV64-NEXT: andi a3, a0, 8
; RV64-NEXT: or a2, a2, a3
; RV64-NEXT: or a1, a1, a2
; RV64-NEXT: srliw a2, a0, 2
; RV64-NEXT: srli a2, a0, 2
; RV64-NEXT: andi a2, a2, 4
; RV64-NEXT: srliw a3, a0, 4
; RV64-NEXT: srli a3, a0, 4
; RV64-NEXT: andi a3, a3, 2
; RV64-NEXT: or a2, a2, a3
; RV64-NEXT: or a1, a1, a2
; RV64-NEXT: srliw a0, a0, 6
; RV64-NEXT: srli a0, a0, 6
; RV64-NEXT: or a0, a1, a0
; RV64-NEXT: ret
%rev = call i7 @llvm.bitreverse.i7(i7 %x)
Expand Down Expand Up @@ -171,36 +171,36 @@ define i24 @bitreverse_i24(i24 %x) {
;
; RV64-LABEL: bitreverse_i24:
; RV64: # %bb.0:
; RV64-NEXT: slli a1, a0, 16
; RV64-NEXT: lui a2, 4096
; RV64-NEXT: addi a2, a2, -1
; RV64-NEXT: and a0, a0, a2
; RV64-NEXT: srliw a0, a0, 16
; RV64-NEXT: or a0, a0, a1
; RV64-NEXT: lui a1, 1048335
; RV64-NEXT: addi a1, a1, 240
; RV64-NEXT: and a3, a1, a2
; RV64-NEXT: lui a1, 4096
; RV64-NEXT: addiw a1, a1, -1
; RV64-NEXT: slli a2, a0, 16
; RV64-NEXT: and a0, a0, a1
; RV64-NEXT: srli a0, a0, 16
; RV64-NEXT: or a0, a0, a2
; RV64-NEXT: lui a2, 1048335
; RV64-NEXT: addiw a2, a2, 240
; RV64-NEXT: and a3, a2, a1
; RV64-NEXT: and a3, a0, a3
; RV64-NEXT: srliw a3, a3, 4
; RV64-NEXT: srli a3, a3, 4
; RV64-NEXT: slli a0, a0, 4
; RV64-NEXT: and a0, a0, a1
; RV64-NEXT: and a0, a0, a2
; RV64-NEXT: or a0, a3, a0
; RV64-NEXT: lui a1, 1047757
; RV64-NEXT: addi a1, a1, -820
; RV64-NEXT: and a3, a1, a2
; RV64-NEXT: lui a2, 1047757
; RV64-NEXT: addiw a2, a2, -820
; RV64-NEXT: and a3, a2, a1
; RV64-NEXT: and a3, a0, a3
; RV64-NEXT: srliw a3, a3, 2
; RV64-NEXT: srli a3, a3, 2
; RV64-NEXT: slli a0, a0, 2
; RV64-NEXT: and a0, a0, a1
; RV64-NEXT: and a0, a0, a2
; RV64-NEXT: or a0, a3, a0
; RV64-NEXT: lui a1, 1047211
; RV64-NEXT: addiw a1, a1, -1366
; RV64-NEXT: and a2, a1, a2
; RV64-NEXT: and a2, a0, a2
; RV64-NEXT: srliw a2, a2, 1
; RV64-NEXT: slliw a0, a0, 1
; RV64-NEXT: and a0, a0, a1
; RV64-NEXT: or a0, a2, a0
; RV64-NEXT: lui a2, 1047211
; RV64-NEXT: addiw a2, a2, -1366
; RV64-NEXT: and a1, a2, a1
; RV64-NEXT: and a1, a0, a1
; RV64-NEXT: srli a1, a1, 1
; RV64-NEXT: slli a0, a0, 1
; RV64-NEXT: and a0, a0, a2
; RV64-NEXT: or a0, a1, a0
; RV64-NEXT: ret
%rev = call i24 @llvm.bitreverse.i24(i24 %x)
ret i24 %rev
Expand Down
16 changes: 12 additions & 4 deletions llvm/test/CodeGen/RISCV/GlobalISel/combine.ll
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,18 @@ define i32 @mul_to_shift(i32 %x) {
; RV32-NEXT: slli a0, a0, 2
; RV32-NEXT: ret
;
; RV64-LABEL: mul_to_shift:
; RV64: # %bb.0:
; RV64-NEXT: slliw a0, a0, 2
; RV64-NEXT: ret
; RV64-O0-LABEL: mul_to_shift:
; RV64-O0: # %bb.0:
; RV64-O0-NEXT: li a1, 2
; RV64-O0-NEXT: sll a0, a0, a1
; RV64-O0-NEXT: ret
;
; RV64-OPT-LABEL: mul_to_shift:
; RV64-OPT: # %bb.0:
; RV64-OPT-NEXT: slli a0, a0, 2
; RV64-OPT-NEXT: ret
%a = mul i32 %x, 4
ret i32 %a
}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; RV64: {{.*}}
8 changes: 4 additions & 4 deletions llvm/test/CodeGen/RISCV/GlobalISel/iabs.ll
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ define i8 @abs8(i8 %x) {
;
; RV64I-LABEL: abs8:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a1, a0, 24
; RV64I-NEXT: sraiw a1, a1, 31
; RV64I-NEXT: slli a1, a0, 56
; RV64I-NEXT: srai a1, a1, 63
; RV64I-NEXT: addw a0, a0, a1
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: ret
Expand Down Expand Up @@ -65,8 +65,8 @@ define i16 @abs16(i16 %x) {
;
; RV64I-LABEL: abs16:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a1, a0, 16
; RV64I-NEXT: sraiw a1, a1, 31
; RV64I-NEXT: slli a1, a0, 48
; RV64I-NEXT: srai a1, a1, 63
; RV64I-NEXT: addw a0, a0, a1
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: ret
Expand Down
Loading
Loading