Skip to content

Commit 15ab569

Browse files
committed
[RISCV] Add software pipeliner support
This patch adds basic support of `MachinePipeliner` and disable it by default. The functionality should be OK and all llvm-test-suite tests have passed.
1 parent 5352478 commit 15ab569

File tree

6 files changed

+178
-0
lines changed

6 files changed

+178
-0
lines changed

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4136,3 +4136,84 @@ bool RISCV::isVLKnownLE(const MachineOperand &LHS, const MachineOperand &RHS) {
41364136
return false;
41374137
return LHS.getImm() <= RHS.getImm();
41384138
}
4139+
4140+
namespace {
4141+
class RISCVPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
4142+
const MachineInstr *LHS;
4143+
const MachineInstr *RHS;
4144+
SmallVector<MachineOperand, 4> Cond;
4145+
4146+
public:
4147+
RISCVPipelinerLoopInfo(const MachineInstr *LHS, const MachineInstr *RHS,
4148+
const SmallVectorImpl<MachineOperand> &Cond)
4149+
: LHS(LHS), RHS(RHS), Cond(Cond.begin(), Cond.end()) {}
4150+
4151+
bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
4152+
// Make the instructions for loop control be placed in stage 0.
4153+
// The predecessors of PredBranch are considered by the caller.
4154+
if (LHS && MI == LHS)
4155+
return true;
4156+
if (RHS && MI == RHS)
4157+
return true;
4158+
return false;
4159+
}
4160+
4161+
std::optional<bool> createTripCountGreaterCondition(
4162+
int TC, MachineBasicBlock &MBB,
4163+
SmallVectorImpl<MachineOperand> &CondParam) override {
4164+
// A branch instruction will be inserted as "if (Cond) goto epilogue".
4165+
// Cond is normalized for such use.
4166+
// The predecessors of the branch are assumed to have already been inserted.
4167+
CondParam = Cond;
4168+
return {};
4169+
}
4170+
4171+
void setPreheader(MachineBasicBlock *NewPreheader) override {}
4172+
4173+
void adjustTripCount(int TripCountAdjust) override {}
4174+
4175+
void disposed() override {}
4176+
};
4177+
} // namespace
4178+
4179+
std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
4180+
RISCVInstrInfo::analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const {
4181+
MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
4182+
SmallVector<MachineOperand, 4> Cond;
4183+
if (analyzeBranch(*LoopBB, TBB, FBB, Cond, /*AllowModify=*/false))
4184+
return nullptr;
4185+
4186+
// Infinite loops are not supported
4187+
if (TBB == LoopBB && FBB == LoopBB)
4188+
return nullptr;
4189+
4190+
// Must be conditional branch
4191+
if (FBB == nullptr)
4192+
return nullptr;
4193+
4194+
assert((TBB == LoopBB || FBB == LoopBB) &&
4195+
"The Loop must be a single-basic-block loop");
4196+
4197+
// Normalization for createTripCountGreaterCondition()
4198+
if (TBB == LoopBB)
4199+
reverseBranchCondition(Cond);
4200+
4201+
const MachineRegisterInfo &MRI = LoopBB->getParent()->getRegInfo();
4202+
auto FindRegDef = [&MRI](MachineOperand &Op) -> const MachineInstr * {
4203+
if (!Op.isReg())
4204+
return nullptr;
4205+
Register Reg = Op.getReg();
4206+
if (!Reg.isVirtual())
4207+
return nullptr;
4208+
return MRI.getVRegDef(Reg);
4209+
};
4210+
4211+
const MachineInstr *LHS = FindRegDef(Cond[1]);
4212+
const MachineInstr *RHS = FindRegDef(Cond[2]);
4213+
if (LHS && LHS->isPHI())
4214+
return nullptr;
4215+
if (RHS && RHS->isPHI())
4216+
return nullptr;
4217+
4218+
return std::make_unique<RISCVPipelinerLoopInfo>(LHS, RHS, Cond);
4219+
}

llvm/lib/Target/RISCV/RISCVInstrInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
293293

294294
unsigned getTailDuplicateSize(CodeGenOptLevel OptLevel) const override;
295295

296+
std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
297+
analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override;
298+
296299
protected:
297300
const RISCVSubtarget &STI;
298301

llvm/lib/Target/RISCV/RISCVSubtarget.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ bool RISCVSubtarget::useRVVForFixedLengthVectors() const {
186186

187187
bool RISCVSubtarget::enableSubRegLiveness() const { return true; }
188188

189+
bool RISCVSubtarget::enableMachinePipeliner() const {
190+
return getSchedModel().hasInstrSchedModel();
191+
}
192+
189193
void RISCVSubtarget::getPostRAMutations(
190194
std::vector<std::unique_ptr<ScheduleDAGMutation>> &Mutations) const {
191195
Mutations.push_back(createMacroFusionDAGMutation(getMacroFusions()));

llvm/lib/Target/RISCV/RISCVSubtarget.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
304304
void getPostRAMutations(std::vector<std::unique_ptr<ScheduleDAGMutation>>
305305
&Mutations) const override;
306306

307+
bool enableMachinePipeliner() const override;
308+
309+
bool useDFAforSMS() const override { return false; }
310+
307311
bool useAA() const override;
308312

309313
unsigned getCacheLineSize() const override {

llvm/lib/Target/RISCV/RISCVTargetMachine.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ static cl::opt<bool>
114114
cl::desc("Enable the RISC-V VL Optimizer pass"),
115115
cl::init(false), cl::Hidden);
116116

117+
static cl::opt<bool>
118+
EnableMachinePipeliner("riscv-enable-pipeliner",
119+
cl::desc("Enable Machine Pipeliner for RISC-V"),
120+
cl::init(false), cl::Hidden);
121+
117122
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
118123
RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
119124
RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
@@ -600,6 +605,9 @@ void RISCVPassConfig::addPreRegAlloc() {
600605
addPass(createRISCVInsertReadWriteCSRPass());
601606
addPass(createRISCVInsertWriteVXRMPass());
602607
addPass(createRISCVLandingPadSetupPass());
608+
609+
if (TM->getOptLevel() != CodeGenOptLevel::None && EnableMachinePipeliner)
610+
addPass(&MachinePipelinerID);
603611
}
604612

605613
void RISCVPassConfig::addFastRegAlloc() {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=riscv64 -mcpu=sifive-p670 -O3 -verify-machineinstrs -riscv-enable-pipeliner=false < %s \
3+
; RUN: | FileCheck %s --check-prefixes=CHECK-NOT-PIPELINED
4+
; RUN: llc -mtriple=riscv64 -mcpu=sifive-p670 -O3 -verify-machineinstrs -riscv-enable-pipeliner=true < %s \
5+
; RUN: | FileCheck %s --check-prefixes=CHECK-PIPELINED
6+
7+
define void @test_1(ptr noalias %in, ptr noalias %out, i32 signext %cnt) "no-builtins" {
8+
; CHECK-NOT-PIPELINED-LABEL: test_1:
9+
; CHECK-NOT-PIPELINED: # %bb.0: # %entry
10+
; CHECK-NOT-PIPELINED-NEXT: blez a2, .LBB0_3
11+
; CHECK-NOT-PIPELINED-NEXT: # %bb.1: # %for.body.preheader
12+
; CHECK-NOT-PIPELINED-NEXT: addi a2, a2, -1
13+
; CHECK-NOT-PIPELINED-NEXT: sh2add.uw a2, a2, a1
14+
; CHECK-NOT-PIPELINED-NEXT: addi a2, a2, 4
15+
; CHECK-NOT-PIPELINED-NEXT: .LBB0_2: # %for.body
16+
; CHECK-NOT-PIPELINED-NEXT: # =>This Inner Loop Header: Depth=1
17+
; CHECK-NOT-PIPELINED-NEXT: lw a3, 0(a1)
18+
; CHECK-NOT-PIPELINED-NEXT: addi a1, a1, 4
19+
; CHECK-NOT-PIPELINED-NEXT: sw a3, 0(a0)
20+
; CHECK-NOT-PIPELINED-NEXT: addi a0, a0, 4
21+
; CHECK-NOT-PIPELINED-NEXT: bne a1, a2, .LBB0_2
22+
; CHECK-NOT-PIPELINED-NEXT: .LBB0_3: # %for.end
23+
; CHECK-NOT-PIPELINED-NEXT: ret
24+
;
25+
; CHECK-PIPELINED-LABEL: test_1:
26+
; CHECK-PIPELINED: # %bb.0: # %entry
27+
; CHECK-PIPELINED-NEXT: blez a2, .LBB0_6
28+
; CHECK-PIPELINED-NEXT: # %bb.1: # %for.body.preheader
29+
; CHECK-PIPELINED-NEXT: lw a3, 0(a1)
30+
; CHECK-PIPELINED-NEXT: addi a2, a2, -1
31+
; CHECK-PIPELINED-NEXT: addi a4, a0, 4
32+
; CHECK-PIPELINED-NEXT: sh2add.uw a6, a2, a1
33+
; CHECK-PIPELINED-NEXT: addi a1, a1, 4
34+
; CHECK-PIPELINED-NEXT: addi a6, a6, 4
35+
; CHECK-PIPELINED-NEXT: beq a1, a6, .LBB0_5
36+
; CHECK-PIPELINED-NEXT: # %bb.2: # %for.body
37+
; CHECK-PIPELINED-NEXT: lw a5, 0(a1)
38+
; CHECK-PIPELINED-NEXT: addi a2, a4, 4
39+
; CHECK-PIPELINED-NEXT: addi a1, a1, 4
40+
; CHECK-PIPELINED-NEXT: beq a1, a6, .LBB0_4
41+
; CHECK-PIPELINED-NEXT: .LBB0_3: # %for.body
42+
; CHECK-PIPELINED-NEXT: # =>This Inner Loop Header: Depth=1
43+
; CHECK-PIPELINED-NEXT: sw a3, 0(a0)
44+
; CHECK-PIPELINED-NEXT: mv a3, a5
45+
; CHECK-PIPELINED-NEXT: lw a5, 0(a1)
46+
; CHECK-PIPELINED-NEXT: mv a0, a4
47+
; CHECK-PIPELINED-NEXT: mv a4, a2
48+
; CHECK-PIPELINED-NEXT: addi a2, a2, 4
49+
; CHECK-PIPELINED-NEXT: addi a1, a1, 4
50+
; CHECK-PIPELINED-NEXT: bne a1, a6, .LBB0_3
51+
; CHECK-PIPELINED-NEXT: .LBB0_4:
52+
; CHECK-PIPELINED-NEXT: sw a3, 0(a0)
53+
; CHECK-PIPELINED-NEXT: mv a0, a4
54+
; CHECK-PIPELINED-NEXT: mv a3, a5
55+
; CHECK-PIPELINED-NEXT: .LBB0_5:
56+
; CHECK-PIPELINED-NEXT: sw a3, 0(a0)
57+
; CHECK-PIPELINED-NEXT: .LBB0_6: # %for.end
58+
; CHECK-PIPELINED-NEXT: ret
59+
entry:
60+
%cmp5 = icmp sgt i32 %cnt, 0
61+
br i1 %cmp5, label %for.body, label %for.end
62+
63+
for.body: ; preds = %entry, %for.body
64+
%i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
65+
%in.addr.07 = phi ptr [ %incdec.ptr, %for.body ], [ %in, %entry ]
66+
%out.addr.06 = phi ptr [ %incdec.ptr1, %for.body ], [ %out, %entry ]
67+
%0 = load i32, ptr %out.addr.06, align 4
68+
store i32 %0, ptr %in.addr.07, align 4
69+
%incdec.ptr = getelementptr inbounds i8, ptr %in.addr.07, i64 4
70+
%incdec.ptr1 = getelementptr inbounds i8, ptr %out.addr.06, i64 4
71+
%inc = add nuw nsw i32 %i.08, 1
72+
%exitcond.not = icmp eq i32 %inc, %cnt
73+
br i1 %exitcond.not, label %for.end, label %for.body
74+
75+
for.end: ; preds = %for.body, %entry
76+
ret void
77+
}
78+

0 commit comments

Comments
 (0)