Skip to content

Commit 6760cf2

Browse files
committed
[RISCV] Add a pass to eliminate special copies in order to facilitate shrink-wrap optimization
Some data types that require extension have redundant copy instructions. This pass removes specific copies to help shrink-wrap optimization.
1 parent d013556 commit 6760cf2

13 files changed

+904
-764
lines changed

llvm/lib/Target/RISCV/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ add_llvm_target(RISCVCodeGen
3434
RISCVCallingConv.cpp
3535
RISCVCodeGenPrepare.cpp
3636
RISCVConstantPoolValue.cpp
37+
RISCVCopyCombine.cpp
3738
RISCVDeadRegisterDefinitions.cpp
3839
RISCVExpandAtomicPseudoInsts.cpp
3940
RISCVExpandPseudoInsts.cpp

llvm/lib/Target/RISCV/RISCV.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ void initializeRISCVCodeGenPreparePass(PassRegistry &);
3030

3131
FunctionPass *createRISCVDeadRegisterDefinitionsPass();
3232
void initializeRISCVDeadRegisterDefinitionsPass(PassRegistry &);
33+
FunctionPass *createRISCVCopyCombinePass();
34+
void initializeRISCVCopyCombinePass(PassRegistry &);
3335

3436
FunctionPass *createRISCVIndirectBranchTrackingPass();
3537
void initializeRISCVIndirectBranchTrackingPass(PassRegistry &);
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
//===- RISCVCopyCombine.cpp - Remove special copy for RISC-V --------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This pass attempts a shrink-wrap optimization for special cases, which is
10+
// effective when data types require extension.
11+
//
12+
// After finalize-isel:
13+
// bb0:
14+
// liveins: $x10, $x11
15+
// %1:gpr = COPY $x11 ---- will be delete in this pass
16+
// %0:gpr = COPY $x10
17+
// %2:gpr = COPY %1:gpr ---- without this pass, sink to bb1 in machine-sink,
18+
// then delete at regalloc
19+
// BEQ %0:gpr, killed %3:gpr, %bb.3 PseudoBR %bb1
20+
//
21+
// bb1:
22+
// bb2:
23+
// BNE %2:gpr, killed %5:gpr, %bb.2
24+
// ...
25+
// After regalloc
26+
// bb0:
27+
// liveins: $x10, $x11
28+
// renamable $x8 = COPY $x11
29+
// renamable $x11 = ADDI $x0, 57 --- def x11, so COPY can not be sink
30+
// BEQ killed renamable $x10, killed renamable $x11, %bb.4
31+
// PseudoBR %bb.1
32+
//
33+
// bb1:
34+
// bb2:
35+
// BEQ killed renamable $x8, killed renamable $x10, %bb.4
36+
//
37+
// ----->
38+
//
39+
// After this pass:
40+
// bb0:
41+
// liveins: $x10, $x11
42+
// %0:gpr = COPY $x10
43+
// %2:gpr = COPY $x11
44+
// BEQ %0:gpr, killed %3:gpr, %bb.3
45+
// PseudoBR %bb1
46+
//
47+
// bb1:
48+
// bb2:
49+
// BNE %2:gpr, killed %5:gpr, %bb.2
50+
// ...
51+
// After regalloc
52+
// bb0:
53+
// liveins: $x10, $x11
54+
// renamable $x12 = ADDI $x0, 57
55+
// renamable $x8 = COPY $x11
56+
// BEQ killed renamable $x10, killed renamable $x11, %bb.4
57+
// PseudoBR %bb.1
58+
//
59+
// bb1:
60+
// bb2:
61+
// BEQ killed renamable $x8, killed renamable $x10, %bb.4
62+
//===----------------------------------------------------------------------===//
63+
64+
#include "RISCV.h"
65+
#include "RISCVSubtarget.h"
66+
#include "llvm/ADT/Statistic.h"
67+
#include "llvm/CodeGen/MachineFunctionPass.h"
68+
69+
using namespace llvm;
70+
#define DEBUG_TYPE "riscv-copy-combine"
71+
#define RISCV_COPY_COMBINE "RISC-V Copy Combine"
72+
73+
STATISTIC(NumCopyDeleted, "Number of copy deleted");
74+
75+
namespace {
76+
class RISCVCopyCombine : public MachineFunctionPass {
77+
public:
78+
static char ID;
79+
const TargetInstrInfo *TII;
80+
MachineRegisterInfo *MRI;
81+
const TargetRegisterInfo *TRI;
82+
83+
RISCVCopyCombine() : MachineFunctionPass(ID) {}
84+
bool runOnMachineFunction(MachineFunction &MF) override;
85+
MachineFunctionProperties getRequiredProperties() const override {
86+
return MachineFunctionProperties().set(
87+
MachineFunctionProperties::Property::IsSSA);
88+
}
89+
90+
StringRef getPassName() const override { return RISCV_COPY_COMBINE; }
91+
92+
private:
93+
bool optimizeBlock(MachineBasicBlock &MBB);
94+
bool copyCombine(MachineOperand &Op);
95+
};
96+
} // end anonymous namespace
97+
98+
char RISCVCopyCombine::ID = 0;
99+
INITIALIZE_PASS(RISCVCopyCombine, DEBUG_TYPE, RISCV_COPY_COMBINE, false, false)
100+
101+
/// Check if it's safe to move From down to To, checking that no physical
102+
/// registers are clobbered.
103+
static bool isSafeToMove(const MachineInstr &From, const MachineInstr &To) {
104+
SmallVector<Register> PhysUses;
105+
for (const MachineOperand &MO : From.all_uses())
106+
if (MO.getReg().isPhysical())
107+
PhysUses.push_back(MO.getReg());
108+
bool SawStore = false;
109+
for (auto II = From.getIterator(); II != To.getIterator(); II++) {
110+
for (Register PhysReg : PhysUses)
111+
if (II->definesRegister(PhysReg, nullptr))
112+
return false;
113+
if (II->mayStore()) {
114+
SawStore = true;
115+
break;
116+
}
117+
}
118+
return From.isSafeToMove(SawStore);
119+
}
120+
121+
bool RISCVCopyCombine::copyCombine(MachineOperand &Op) {
122+
if (!Op.isReg())
123+
return false;
124+
125+
Register Reg = Op.getReg();
126+
if (!Reg.isVirtual())
127+
return false;
128+
129+
MachineInstr *MI = MRI->getVRegDef(Reg);
130+
if (MI->getOpcode() != RISCV::COPY)
131+
return false;
132+
133+
Register Op1reg = MI->getOperand(1).getReg();
134+
if (!MRI->hasOneUse(Op1reg) || !Op1reg.isVirtual() ||
135+
!MI->getOperand(0).getReg().isVirtual())
136+
return false;
137+
138+
MachineInstr *Src = MRI->getVRegDef(Op1reg);
139+
if (!Src || Src->hasUnmodeledSideEffects() ||
140+
Src->getOpcode() != RISCV::COPY || Src->getParent() != MI->getParent() ||
141+
Src->getNumDefs() != 1)
142+
return false;
143+
144+
if (!isSafeToMove(*Src, *MI))
145+
return false;
146+
147+
Register SrcOp1reg = Src->getOperand(1).getReg();
148+
MRI->replaceRegWith(Op1reg, SrcOp1reg);
149+
MRI->clearKillFlags(SrcOp1reg);
150+
LLVM_DEBUG(dbgs() << "Deleting this copy instruction "; Src->print(dbgs()));
151+
++NumCopyDeleted;
152+
Src->eraseFromParent();
153+
return true;
154+
}
155+
156+
bool RISCVCopyCombine::optimizeBlock(MachineBasicBlock &MBB) {
157+
MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
158+
SmallVector<MachineOperand, 3> Cond;
159+
if (TII->analyzeBranch(MBB, TBB, FBB, Cond, /*AllowModify*/ false) ||
160+
Cond.empty())
161+
return false;
162+
163+
if (!TBB || Cond.size() != 3)
164+
return false;
165+
166+
return copyCombine(Cond[1]) || copyCombine(Cond[2]);
167+
}
168+
169+
bool RISCVCopyCombine::runOnMachineFunction(MachineFunction &MF) {
170+
if (skipFunction(MF.getFunction()))
171+
return false;
172+
173+
TII = MF.getSubtarget().getInstrInfo();
174+
MRI = &MF.getRegInfo();
175+
TRI = MRI->getTargetRegisterInfo();
176+
177+
bool Changed = false;
178+
for (MachineBasicBlock &MBB : MF)
179+
Changed |= optimizeBlock(MBB);
180+
181+
return Changed;
182+
}
183+
184+
FunctionPass *llvm::createRISCVCopyCombinePass() {
185+
return new RISCVCopyCombine();
186+
}

llvm/lib/Target/RISCV/RISCVTargetMachine.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
128128
initializeRISCVPostLegalizerCombinerPass(*PR);
129129
initializeKCFIPass(*PR);
130130
initializeRISCVDeadRegisterDefinitionsPass(*PR);
131+
initializeRISCVCopyCombinePass(*PR);
131132
initializeRISCVLateBranchOptPass(*PR);
132133
initializeRISCVMakeCompressibleOptPass(*PR);
133134
initializeRISCVGatherScatterLoweringPass(*PR);
@@ -455,6 +456,7 @@ bool RISCVPassConfig::addRegAssignAndRewriteFast() {
455456
if (TM->getOptLevel() != CodeGenOptLevel::None &&
456457
EnableRISCVDeadRegisterElimination)
457458
addPass(createRISCVDeadRegisterDefinitionsPass());
459+
458460
return TargetPassConfig::addRegAssignAndRewriteFast();
459461
}
460462

@@ -598,6 +600,7 @@ void RISCVPassConfig::addPreEmitPass2() {
598600
}
599601

600602
void RISCVPassConfig::addMachineSSAOptimization() {
603+
addPass(createRISCVCopyCombinePass());
601604
addPass(createRISCVVectorPeepholePass());
602605
addPass(createRISCVFoldMemOffsetPass());
603606

llvm/test/CodeGen/RISCV/O3-pipeline.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
; CHECK-NEXT: Lazy Block Frequency Analysis
9797
; CHECK-NEXT: RISC-V DAG->DAG Pattern Instruction Selection
9898
; CHECK-NEXT: Finalize ISel and expand pseudo-instructions
99+
; CHECK-NEXT: RISC-V Copy Combine
99100
; CHECK-NEXT: RISC-V Vector Peephole Optimization
100101
; CHECK-NEXT: RISC-V Fold Memory Offset
101102
; CHECK-NEXT: Lazy Machine Block Frequency Analysis

0 commit comments

Comments
 (0)