Skip to content

Commit 9cdd863

Browse files
committed
[RISCV] Add hasAllNBitUsers Functional change, change allows for the generation of packw instructions along with other generic instructions with narrow w type.
Signed-off-by: Luke Quinn <[email protected]>
1 parent 40d2d95 commit 9cdd863

File tree

10 files changed

+240
-169
lines changed

10 files changed

+240
-169
lines changed

llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,20 @@ class RISCVInstructionSelector : public InstructionSelector {
5757
const TargetRegisterClass *
5858
getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) const;
5959

60+
static constexpr unsigned MaxRecursionDepth = 6;
61+
6062
// const MachineInstr &MI
61-
bool hasAllNBitUsers(const MachineInstr &MI, unsigned Bits, const unsigned Depth = 0) const;
62-
bool hasAllBUsers(const MachineInstr &MI) const { return hasAllNBitUsers(MI, 8); }
63-
bool hasAllHUsers(const MachineInstr &MI) const { return hasAllNBitUsers(MI, 16); }
64-
bool hasAllWUsers(const MachineInstr &MI) const { return hasAllNBitUsers(MI, 32); }
63+
bool hasAllNBitUsers(const MachineInstr &MI, unsigned Bits,
64+
const unsigned Depth = 0) const;
65+
bool hasAllBUsers(const MachineInstr &MI) const {
66+
return hasAllNBitUsers(MI, 8);
67+
}
68+
bool hasAllHUsers(const MachineInstr &MI) const {
69+
return hasAllNBitUsers(MI, 16);
70+
}
71+
bool hasAllWUsers(const MachineInstr &MI) const {
72+
return hasAllNBitUsers(MI, 32);
73+
}
6574

6675
bool isRegInGprb(Register Reg) const;
6776
bool isRegInFprb(Register Reg) const;
@@ -192,9 +201,78 @@ RISCVInstructionSelector::RISCVInstructionSelector(
192201
{
193202
}
194203

195-
bool RISCVInstructionSelector::hasAllNBitUsers(const MachineInstr &MI, unsigned Bits, const unsigned Depth) const {
204+
// Mimics optimizations in ISel and RISCVOptWInst Pass
205+
bool RISCVInstructionSelector::hasAllNBitUsers(const MachineInstr &MI,
206+
unsigned Bits,
207+
const unsigned Depth) const {
208+
209+
assert((MI.getOpcode() == TargetOpcode::G_ADD ||
210+
MI.getOpcode() == TargetOpcode::G_SUB ||
211+
MI.getOpcode() == TargetOpcode::G_MUL ||
212+
MI.getOpcode() == TargetOpcode::G_SHL ||
213+
MI.getOpcode() == TargetOpcode::G_LSHR ||
214+
MI.getOpcode() == TargetOpcode::G_AND ||
215+
MI.getOpcode() == TargetOpcode::G_OR ||
216+
MI.getOpcode() == TargetOpcode::G_XOR ||
217+
MI.getOpcode() == TargetOpcode::G_SEXT_INREG || Depth != 0) &&
218+
"Unexpected opcode");
219+
220+
if (Depth >= RISCVInstructionSelector::MaxRecursionDepth)
196221
return false;
197-
};
222+
223+
auto DestReg = MI.getOperand(0).getReg();
224+
for (auto &UserOp : MRI->use_nodbg_operands(DestReg)) {
225+
assert(UserOp.getParent() && "UserOp must have a parent");
226+
const MachineInstr &UserMI = *UserOp.getParent();
227+
unsigned OpIdx = UserOp.getOperandNo();
228+
229+
switch (UserMI.getOpcode()) {
230+
default:
231+
return false;
232+
case RISCV::ADDW:
233+
case RISCV::ADDIW:
234+
case RISCV::SUBW:
235+
if (Bits >= 32)
236+
break;
237+
return false;
238+
case RISCV::SLL:
239+
case RISCV::SRA:
240+
case RISCV::SRL:
241+
// Shift amount operands only use log2(Xlen) bits.
242+
if (OpIdx == 2 && Bits >= Log2_32(Subtarget->getXLen()))
243+
break;
244+
return false;
245+
case RISCV::SLLI:
246+
// SLLI only uses the lower (XLen - ShAmt) bits.
247+
if (Bits >= Subtarget->getXLen() - UserMI.getOperand(2).getImm())
248+
break;
249+
return false;
250+
case RISCV::ANDI:
251+
if (Bits >= (unsigned)llvm::bit_width<uint64_t>(
252+
(uint64_t)UserMI.getOperand(2).getImm()))
253+
break;
254+
goto RecCheck;
255+
case RISCV::AND:
256+
case RISCV::OR:
257+
case RISCV::XOR:
258+
RecCheck:
259+
if (hasAllNBitUsers(UserMI, Bits, Depth + 1))
260+
break;
261+
return false;
262+
case RISCV::SRLI: {
263+
unsigned ShAmt = UserMI.getOperand(2).getImm();
264+
// If we are shifting right by less than Bits, and users don't demand any
265+
// bits that were shifted into [Bits-1:0], then we can consider this as an
266+
// N-Bit user.
267+
if (Bits > ShAmt && hasAllNBitUsers(UserMI, Bits - ShAmt, Depth + 1))
268+
break;
269+
return false;
270+
}
271+
}
272+
}
273+
274+
return true;
275+
}
198276

199277
InstructionSelector::ComplexRendererFns
200278
RISCVInstructionSelector::selectShiftMask(MachineOperand &Root,

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,17 +1943,17 @@ def : Pat<(i64 (shl (and GPR:$rs1, 0xffffffff), uimm5:$shamt)),
19431943

19441944
class binop_allhusers<SDPatternOperator operator>
19451945
: PatFrag<(ops node:$lhs, node:$rhs),
1946-
(XLenVT (operator node:$lhs, node:$rhs)), [{
1946+
(XLenVT(operator node:$lhs, node:$rhs)), [{
19471947
return hasAllHUsers(Node);
19481948
}]> {
1949-
let GISelPredicateCode = [{ return hasAllHUsers(MI); }];
1949+
let GISelPredicateCode = [{ return hasAllHUsers(MI); }];
19501950
}
19511951

19521952
// PatFrag to allow ADDW/SUBW/MULW/SLLW to be selected from i64 add/sub/mul/shl
19531953
// if only the lower 32 bits of their result is used.
19541954
class binop_allwusers<SDPatternOperator operator>
1955-
: PatFrag<(ops node:$lhs, node:$rhs),
1956-
(i64 (operator node:$lhs, node:$rhs)), [{
1955+
: PatFrag<(ops node:$lhs, node:$rhs), (i64(operator node:$lhs, node:$rhs)),
1956+
[{
19571957
return hasAllWUsers(Node);
19581958
}]> {
19591959
let GISelPredicateCode = [{ return hasAllWUsers(MI); }];

llvm/test/CodeGen/RISCV/GlobalISel/combine.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ define i32 @constant_to_rhs(i32 %x) {
2020
; RV64-O0: # %bb.0:
2121
; RV64-O0-NEXT: mv a1, a0
2222
; RV64-O0-NEXT: li a0, 1
23-
; RV64-O0-NEXT: add a0, a0, a1
23+
; RV64-O0-NEXT: addw a0, a0, a1
2424
; RV64-O0-NEXT: sext.w a0, a0
2525
; RV64-O0-NEXT: ret
2626
;

llvm/test/CodeGen/RISCV/GlobalISel/div-by-constant.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ define i32 @udiv_constant_add(i32 %a) nounwind {
6666
; RV64IM-NEXT: srli a2, a2, 32
6767
; RV64IM-NEXT: mul a1, a2, a1
6868
; RV64IM-NEXT: srli a1, a1, 32
69-
; RV64IM-NEXT: sub a0, a0, a1
69+
; RV64IM-NEXT: subw a0, a0, a1
7070
; RV64IM-NEXT: srliw a0, a0, 1
7171
; RV64IM-NEXT: add a0, a0, a1
7272
; RV64IM-NEXT: srliw a0, a0, 2
@@ -79,7 +79,7 @@ define i32 @udiv_constant_add(i32 %a) nounwind {
7979
; RV64IMZB-NEXT: zext.w a2, a0
8080
; RV64IMZB-NEXT: mul a1, a2, a1
8181
; RV64IMZB-NEXT: srli a1, a1, 32
82-
; RV64IMZB-NEXT: sub a0, a0, a1
82+
; RV64IMZB-NEXT: subw a0, a0, a1
8383
; RV64IMZB-NEXT: srliw a0, a0, 1
8484
; RV64IMZB-NEXT: add a0, a0, a1
8585
; RV64IMZB-NEXT: srliw a0, a0, 2
@@ -265,7 +265,7 @@ define i8 @udiv8_constant_add(i8 %a) nounwind {
265265
; RV64-NEXT: andi a2, a0, 255
266266
; RV64-NEXT: mul a1, a2, a1
267267
; RV64-NEXT: srli a1, a1, 8
268-
; RV64-NEXT: sub a0, a0, a1
268+
; RV64-NEXT: subw a0, a0, a1
269269
; RV64-NEXT: andi a0, a0, 255
270270
; RV64-NEXT: srli a0, a0, 1
271271
; RV64-NEXT: add a0, a0, a1

0 commit comments

Comments
 (0)