LLVM: lib/Target/AArch64/AArch64ConditionOptimizer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
82#include
83#include
84#include
85
86using namespace llvm;
87
88#define DEBUG_TYPE "aarch64-condopt"
89
90STATISTIC(NumConditionsAdjusted, "Number of conditions adjusted");
91
92namespace {
93
98
99public:
100
101
102 using CmpInfo = std::tuple<int, unsigned, AArch64CC::CondCode>;
103
104 static char ID;
105
107
108 void getAnalysisUsage(AnalysisUsage &AU) const override;
109 MachineInstr *findSuitableCompare(MachineBasicBlock *MBB);
111 void modifyCmp(MachineInstr *CmpMI, const CmpInfo &Info);
112 bool adjustTo(MachineInstr *CmpMI, AArch64CC::CondCode Cmp, MachineInstr *To,
113 int ToImm);
114 bool runOnMachineFunction(MachineFunction &MF) override;
115
116 StringRef getPassName() const override {
117 return "AArch64 Condition Optimizer";
118 }
119};
120
121}
122
123char AArch64ConditionOptimizer::ID = 0;
124
126 "AArch64 CondOpt Pass", false, false)
130
132 return new AArch64ConditionOptimizer();
133}
134
135void AArch64ConditionOptimizer::getAnalysisUsage(AnalysisUsage &AU) const {
139}
140
141
142
143
144MachineInstr *AArch64ConditionOptimizer::findSuitableCompare(
145 MachineBasicBlock *MBB) {
148 return nullptr;
149
150 if (Term->getOpcode() != AArch64::Bcc)
151 return nullptr;
152
153
155 if (SuccBB->isLiveIn(AArch64::NZCV))
156 return nullptr;
157
158
161 MachineInstr &I = *It;
162 assert(.isTerminator() && "Spurious terminator");
163
164 if (I.readsRegister(AArch64::NZCV, nullptr))
165 return nullptr;
166 switch (I.getOpcode()) {
167
168 case AArch64::SUBSWri:
169 case AArch64::SUBSXri:
170
171 case AArch64::ADDSWri:
172 case AArch64::ADDSXri: {
174 if (.getOperand(2).isImm()) {
175 LLVM_DEBUG(dbgs() << "Immediate of cmp is symbolic, " << I << '\n');
176 return nullptr;
177 } else if (I.getOperand(2).getImm() << ShiftAmt >= 0xfff) {
178 LLVM_DEBUG(dbgs() << "Immediate of cmp may be out of range, " << I
179 << '\n');
180 return nullptr;
181 } else if (->use_nodbg_empty(I.getOperand(0).getReg())) {
182 LLVM_DEBUG(dbgs() << "Destination of cmp is not dead, " << I << '\n');
183 return nullptr;
184 }
185 return &I;
186 }
187
188
189
190
191
192
193 case AArch64::FCMPDri:
194 case AArch64::FCMPSri:
195 case AArch64::FCMPESri:
196 case AArch64::FCMPEDri:
197
198 case AArch64::SUBSWrr:
199 case AArch64::SUBSXrr:
200 case AArch64::ADDSWrr:
201 case AArch64::ADDSXrr:
202 case AArch64::FCMPSrr:
203 case AArch64::FCMPDrr:
204 case AArch64::FCMPESrr:
205 case AArch64::FCMPEDrr:
206
207 return nullptr;
208 }
209 }
211 << '\n');
212 return nullptr;
213}
214
215
217 switch (Opc) {
218 case AArch64::ADDSWri: return AArch64::SUBSWri;
219 case AArch64::ADDSXri: return AArch64::SUBSXri;
220 case AArch64::SUBSWri: return AArch64::ADDSWri;
221 case AArch64::SUBSXri: return AArch64::ADDSXri;
222 default:
224 }
225}
226
227
229 switch (Cmp) {
234 default:
236 }
237}
238
239
240
241AArch64ConditionOptimizer::CmpInfo AArch64ConditionOptimizer::adjustCmp(
244
245
246
247 bool Negative = (Opc == AArch64::ADDSWri || Opc == AArch64::ADDSXri);
248
250
251 if (Negative) {
252 Correction = -Correction;
253 }
254
256 const int NewImm = std::abs(OldImm + Correction);
257
258
259
260 if (OldImm == 0 && ((Negative && Correction == 1) ||
261 (!Negative && Correction == -1))) {
263 }
264
266}
267
268
269void AArch64ConditionOptimizer::modifyCmp(MachineInstr *CmpMI,
270 const CmpInfo &Info) {
272 unsigned Opc;
274 std::tie(Imm, Opc, Cmp) = Info;
275
276 MachineBasicBlock *const MBB = CmpMI->getParent();
277
278
285
286
287
289
290
295
296 ++NumConditionsAdjusted;
297}
298
299
300
301
303
305 assert(Cond.size() == 1 && "Unknown Cond array format");
307 return true;
308 }
309 return false;
310}
311
312
313
314
315bool AArch64ConditionOptimizer::adjustTo(MachineInstr *CmpMI,
317{
318 CmpInfo Info = adjustCmp(CmpMI, Cmp);
319 if (std::get<0>(Info) == ToImm && std::get<1>(Info) == To->getOpcode()) {
320 modifyCmp(CmpMI, Info);
321 return true;
322 }
323 return false;
324}
325
326bool AArch64ConditionOptimizer::runOnMachineFunction(MachineFunction &MF) {
327 LLVM_DEBUG(dbgs() << "********** AArch64 Conditional Compares **********\n"
328 << "********** Function: " << MF.getName() << '\n');
330 return false;
331
333 DomTree = &getAnalysis().getDomTree();
335
337
338
339
340
341
342
344 MachineBasicBlock *HBB = I->getBlock();
345
347 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
349 continue;
350 }
351
352
353 if ( || TBB == HBB) {
354 continue;
355 }
356
358 MachineBasicBlock *TBB_TBB = nullptr, *TBB_FBB = nullptr;
360 continue;
361 }
362
363 MachineInstr *HeadCmpMI = findSuitableCompare(HBB);
364 if (!HeadCmpMI) {
365 continue;
366 }
367
368 MachineInstr *TrueCmpMI = findSuitableCompare(TBB);
369 if (!TrueCmpMI) {
370 continue;
371 }
372
374 if (HeadCond.empty() || (HeadCond, HeadCmp)) {
375 continue;
376 }
377
379 if (TrueCond.empty() || (TrueCond, TrueCmp)) {
380 continue;
381 }
382
385
388 << '\n');
389 LLVM_DEBUG(dbgs() << "\timmediate: " << HeadImm << '\n');
390
393 << '\n');
394 LLVM_DEBUG(dbgs() << "\timmediate: " << TrueImm << '\n');
395
398 std::abs(TrueImm - HeadImm) == 2) {
399
400
401
402
403
404
405
406
407
408
409 CmpInfo HeadCmpInfo = adjustCmp(HeadCmpMI, HeadCmp);
410 CmpInfo TrueCmpInfo = adjustCmp(TrueCmpMI, TrueCmp);
411 if (std::get<0>(HeadCmpInfo) == std::get<0>(TrueCmpInfo) &&
412 std::get<1>(HeadCmpInfo) == std::get<1>(TrueCmpInfo)) {
413 modifyCmp(HeadCmpMI, HeadCmpInfo);
414 modifyCmp(TrueCmpMI, TrueCmpInfo);
416 }
419 std::abs(TrueImm - HeadImm) == 1) {
420
421
422
423
424
425
426
427
428
429
430
431
432 bool adjustHeadCond = (HeadImm < TrueImm);
434 adjustHeadCond = !adjustHeadCond;
435 }
436
437 if (adjustHeadCond) {
438 Changed |= adjustTo(HeadCmpMI, HeadCmp, TrueCmpMI, TrueImm);
439 } else {
440 Changed |= adjustTo(TrueCmpMI, TrueCmp, HeadCmpMI, HeadImm);
441 }
442 }
443
444
445 }
446
448}
unsigned const MachineRegisterInfo * MRI
static int getComplementOpc(int Opc)
Definition AArch64ConditionOptimizer.cpp:216
static AArch64CC::CondCode getAdjustedCmp(AArch64CC::CondCode Cmp)
Definition AArch64ConditionOptimizer.cpp:228
static bool parseCond(ArrayRef< MachineOperand > Cond, AArch64CC::CondCode &CC)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const TargetInstrInfo & TII
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
iterator_range< succ_iterator > successors()
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
TargetInstrInfo - Interface to description of machine instruction set.
virtual bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
virtual const TargetInstrInfo * getInstrInfo() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static const char * getCondCodeName(CondCode Code)
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createAArch64ConditionOptimizerPass()
Definition AArch64ConditionOptimizer.cpp:131
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
DomTreeNodeBase< MachineBasicBlock > MachineDomTreeNode
iterator_range< df_iterator< T > > depth_first(const T &G)
IterT prev_nodbg(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It, then continue decrementing it while it points to a debug instruction.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.