LLVM: lib/Target/AArch64/GISel/AArch64PostSelectOptimize.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
26
27#define DEBUG_TYPE "aarch64-post-select-optimize"
28
29using namespace llvm;
30
31namespace {
33public:
34 static char ID;
35
37
38 StringRef getPassName() const override {
39 return "AArch64 Post Select Optimizer";
40 }
41
43
44 void getAnalysisUsage(AnalysisUsage &AU) const override;
45
46private:
49
52};
53}
54
55void AArch64PostSelectOptimize::getAnalysisUsage(AnalysisUsage &AU) const {
60}
61
63 switch (Opc) {
64 default:
65 return 0;
66 case AArch64::SUBSXrr:
67 return AArch64::SUBXrr;
68 case AArch64::SUBSWrr:
69 return AArch64::SUBWrr;
70 case AArch64::SUBSXrs:
71 return AArch64::SUBXrs;
72 case AArch64::SUBSWrs:
73 return AArch64::SUBWrs;
74 case AArch64::SUBSXri:
75 return AArch64::SUBXri;
76 case AArch64::SUBSWri:
77 return AArch64::SUBWri;
78 case AArch64::ADDSXrr:
79 return AArch64::ADDXrr;
80 case AArch64::ADDSWrr:
81 return AArch64::ADDWrr;
82 case AArch64::ADDSXrs:
83 return AArch64::ADDXrs;
84 case AArch64::ADDSWrs:
85 return AArch64::ADDWrs;
86 case AArch64::ADDSXri:
87 return AArch64::ADDXri;
88 case AArch64::ADDSWri:
89 return AArch64::ADDWri;
90 case AArch64::SBCSXr:
91 return AArch64::SBCXr;
92 case AArch64::SBCSWr:
93 return AArch64::SBCWr;
94 case AArch64::ADCSXr:
95 return AArch64::ADCXr;
96 case AArch64::ADCSWr:
97 return AArch64::ADCWr;
98 }
99}
100
101bool AArch64PostSelectOptimize::doPeepholeOpts(MachineBasicBlock &MBB) {
104 bool CurrentIterChanged = foldSimpleCrossClassCopies(MI);
105 if (!CurrentIterChanged)
106 CurrentIterChanged |= foldCopyDup(MI);
107 Changed |= CurrentIterChanged;
108 }
110}
111
112bool AArch64PostSelectOptimize::foldSimpleCrossClassCopies(MachineInstr &MI) {
113 auto *MF = MI.getMF();
114 auto &MRI = MF->getRegInfo();
115
116 if (.isCopy())
117 return false;
118
119 if (MI.getOperand(1).getSubReg())
120 return false;
121
122 Register Src = MI.getOperand(1).getReg();
123 Register Dst = MI.getOperand(0).getReg();
124
125 if (Src.isPhysical() || Dst.isPhysical())
126 return false;
127
128 const TargetRegisterClass *SrcRC = MRI.getRegClass(Src);
129 const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
130
131 if (SrcRC == DstRC)
132 return false;
133
134
136
137
138
139
140 if (.hasOneNonDBGUse(Src))
141 return false;
142
143
144
145 if (.constrainRegClass(Src, DstRC, 25))
146 return false;
148
149
150
151 } else {
152 return false;
153 }
154
155 MRI.replaceRegWith(Dst, Src);
156 MI.eraseFromParent();
157 return true;
158}
159
160bool AArch64PostSelectOptimize::foldCopyDup(MachineInstr &MI) {
161 if (.isCopy())
162 return false;
163
164 auto *MF = MI.getMF();
165 auto &MRI = MF->getRegInfo();
166 auto *TII = MF->getSubtarget().getInstrInfo();
167
168
169
170 Register Dst = MI.getOperand(0).getReg();
171 Register Src = MI.getOperand(1).getReg();
172
173 if (!Dst.isVirtual() || !Src.isVirtual())
174 return false;
175
176 auto TryMatchDUP = [&](const TargetRegisterClass *GPRRegClass,
177 const TargetRegisterClass *FPRRegClass, unsigned DUP,
178 unsigned UMOV) {
179 if (MRI.getRegClassOrNull(Dst) != GPRRegClass ||
180 MRI.getRegClassOrNull(Src) != FPRRegClass)
181 return false;
182
183
184
185
186
187 for (auto &Use : MRI.use_nodbg_instructions(Dst)) {
188 if (.isCopy())
189 continue;
190
191 Register UseOp0 = Use.getOperand(0).getReg();
192 Register UseOp1 = Use.getOperand(1).getReg();
194 return false;
195
196 if (MRI.getRegClassOrNull(UseOp0) == FPRRegClass &&
197 MRI.getRegClassOrNull(UseOp1) == GPRRegClass)
198 return false;
199 }
200
201 MachineInstr *SrcMI = MRI.getUniqueVRegDef(Src);
202 if (!SrcMI || SrcMI->getOpcode() != DUP || .hasOneNonDBGUse(Src))
203 return false;
204
207
212 MI.eraseFromParent();
213 return true;
214 };
215
216 return TryMatchDUP(&AArch64::GPR32RegClass, &AArch64::FPR32RegClass,
217 AArch64::DUPi32, AArch64::UMOVvi32) ||
218 TryMatchDUP(&AArch64::GPR64RegClass, &AArch64::FPR64RegClass,
219 AArch64::DUPi64, AArch64::UMOVvi64);
220}
221
222bool AArch64PostSelectOptimize::optimizeNZCVDefs(MachineBasicBlock &MBB) {
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
253 const auto &TII = Subtarget.getInstrInfo();
254 auto TRI = Subtarget.getRegisterInfo();
255 auto RBI = Subtarget.getRegBankInfo();
256 auto &MRI = MF.getRegInfo();
257
259 LRU.addLiveOuts(MBB);
260
262 bool NZCVDead = LRU.available(AArch64::NZCV);
263 if (NZCVDead && II.definesRegister(AArch64::NZCV, nullptr)) {
264
266 int DeadNZCVIdx =
267 II.findRegisterDefOperandIdx(AArch64::NZCV, nullptr);
268 if (DeadNZCVIdx != -1) {
269 if (NewOpc) {
270
271 LLVM_DEBUG(dbgs() << "Post-select optimizer: converting flag-setting "
272 "op: "
273 << II);
274 II.setDesc(TII->get(NewOpc));
275 II.removeOperand(DeadNZCVIdx);
276
277
278
280 II.getOperand(0), 0);
282 } else {
283
284
285 II.getOperand(DeadNZCVIdx).setIsDead();
286 }
287 }
288 }
289 LRU.stepBackward(II);
290 }
292}
293
294bool AArch64PostSelectOptimize::runOnMachineFunction(MachineFunction &MF) {
296 return false;
298
300 for (auto &BB : MF) {
301 Changed |= optimizeNZCVDefs(BB);
302 Changed |= doPeepholeOpts(BB);
303 }
305}
306
307char AArch64PostSelectOptimize::ID = 0;
309 "Optimize AArch64 selected instructions",
310 false, false)
312 "Optimize AArch64 selected instructions", false,
314
315namespace llvm {
317 return new AArch64PostSelectOptimize();
318}
319}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned getNonFlagSettingVariant(unsigned Opc)
Definition AArch64PostSelectOptimize.cpp:62
const TargetInstrInfo & TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Target-Independent Code Generator Pass Configuration Options pass.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
FunctionPass class - This class is used to implement most global optimizations.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
reverse_iterator rbegin()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineFunctionProperties & getProperties() const
Get the function properties.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
Register getReg() const
getReg - Returns the register number.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
StringRef - Represent a constant reference to a string, i.e.
bool hasSubClass(const TargetRegisterClass *RC) const
Return true if the specified TargetRegisterClass is a proper sub-class of this TargetRegisterClass.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
NodeAddr< UseNode * > Use
This is an optimization pass for GlobalISel generic memory operations.
FunctionPass * createAArch64PostSelectOptimize()
Definition AArch64PostSelectOptimize.cpp:316
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
auto instructionsWithoutDebug(IterT It, IterT End, bool SkipPseudoOp=true)
Construct a range iterator which begins at It and moves forwards until End is reached,...
LLVM_ABI void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.