88 #define DEBUG_TYPE "aarch64-condopt" 90 STATISTIC(NumConditionsAdjusted,
"Number of conditions adjusted");
102 using CmpInfo = std::tuple<int, unsigned, AArch64CC::CondCode>;
119 return "AArch64 Condition Optimizer";
128 "AArch64 CondOpt Pass",
false,
false)
134 return new AArch64ConditionOptimizer();
137 void AArch64ConditionOptimizer::getAnalysisUsage(
AnalysisUsage &AU)
const {
146 MachineInstr *AArch64ConditionOptimizer::findSuitableCompare(
152 if (I->getOpcode() != AArch64::Bcc)
157 if (SuccBB->isLiveIn(AArch64::NZCV))
163 assert(!I->isTerminator() &&
"Spurious terminator");
165 if (I->readsRegister(AArch64::NZCV))
167 switch (I->getOpcode()) {
169 case AArch64::SUBSWri:
170 case AArch64::SUBSXri:
172 case AArch64::ADDSWri:
173 case AArch64::ADDSXri: {
175 if (!I->getOperand(2).isImm()) {
176 LLVM_DEBUG(
dbgs() <<
"Immediate of cmp is symbolic, " << *I <<
'\n');
178 }
else if (I->getOperand(2).getImm() << ShiftAmt >= 0xfff) {
179 LLVM_DEBUG(
dbgs() <<
"Immediate of cmp may be out of range, " << *I
182 }
else if (!
MRI->use_empty(I->getOperand(0).getReg())) {
183 LLVM_DEBUG(
dbgs() <<
"Destination of cmp is not dead, " << *I <<
'\n');
194 case AArch64::FCMPDri:
195 case AArch64::FCMPSri:
196 case AArch64::FCMPESri:
197 case AArch64::FCMPEDri:
199 case AArch64::SUBSWrr:
200 case AArch64::SUBSXrr:
201 case AArch64::ADDSWrr:
202 case AArch64::ADDSXrr:
203 case AArch64::FCMPSrr:
204 case AArch64::FCMPDrr:
205 case AArch64::FCMPESrr:
206 case AArch64::FCMPEDrr:
219 case AArch64::ADDSWri:
return AArch64::SUBSWri;
220 case AArch64::ADDSXri:
return AArch64::SUBSXri;
221 case AArch64::SUBSWri:
return AArch64::ADDSWri;
222 case AArch64::SUBSXri:
return AArch64::ADDSXri;
242 AArch64ConditionOptimizer::CmpInfo AArch64ConditionOptimizer::adjustCmp(
248 bool Negative = (Opc == AArch64::ADDSWri || Opc == AArch64::ADDSXri);
253 Correction = -Correction;
257 const int NewImm =
std::abs(OldImm + Correction);
261 if (OldImm == 0 && ((Negative && Correction == 1) ||
262 (!Negative && Correction == -1))) {
270 void AArch64ConditionOptimizer::modifyCmp(
MachineInstr *CmpMI,
271 const CmpInfo &
Info) {
275 std::tie(Imm, Opc, Cmp) =
Info;
299 ++NumConditionsAdjusted;
307 if (Cond[0].getImm() != -1) {
308 assert(Cond.
size() == 1 &&
"Unknown Cond array format");
318 bool AArch64ConditionOptimizer::adjustTo(
MachineInstr *CmpMI,
321 CmpInfo Info = adjustCmp(CmpMI, Cmp);
322 if (std::get<0>(Info) == ToImm && std::get<1>(Info) == To->
getOpcode()) {
323 modifyCmp(CmpMI, Info);
329 bool AArch64ConditionOptimizer::runOnMachineFunction(
MachineFunction &MF) {
330 LLVM_DEBUG(
dbgs() <<
"********** AArch64 Conditional Compares **********\n" 331 <<
"********** Function: " << MF.
getName() <<
'\n');
336 DomTree = &getAnalysis<MachineDominatorTree>();
339 bool Changed =
false;
356 if (!TBB || TBB == HBB) {
412 CmpInfo HeadCmpInfo = adjustCmp(HeadCmpMI, HeadCmp);
413 CmpInfo TrueCmpInfo = adjustCmp(TrueCmpMI, TrueCmp);
414 if (std::get<0>(HeadCmpInfo) == std::get<0>(TrueCmpInfo) &&
415 std::get<1>(HeadCmpInfo) == std::get<1>(TrueCmpInfo)) {
416 modifyCmp(HeadCmpMI, HeadCmpInfo);
417 modifyCmp(TrueCmpMI, TrueCmpInfo);
435 bool adjustHeadCond = (HeadImm < TrueImm);
437 adjustHeadCond = !adjustHeadCond;
440 if (adjustHeadCond) {
441 Changed |= adjustTo(HeadCmpMI, HeadCmp, TrueCmpMI, TrueImm);
443 Changed |= adjustTo(TrueCmpMI, TrueCmp, HeadCmpMI, HeadImm);
Pass interface - Implemented by all 'passes'.
const MachineInstrBuilder & add(const MachineOperand &MO) const
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This class represents lattice values for constants.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
STATISTIC(NumFunctions, "Total number of functions")
iterator_range< succ_iterator > successors()
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e...
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static const char * getCondCodeName(CondCode Code)
Base class for the actual dominator tree node.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
virtual const TargetInstrInfo * getInstrInfo() const
Analysis containing CSE Info
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
TargetInstrInfo - Interface to description of machine instruction set.
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
static int getComplementOpc(int Opc)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
size_t size() const
size - Get the array size.
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
INITIALIZE_PASS_BEGIN(AArch64ConditionOptimizer, "aarch64-condopt", "AArch64 CondOpt Pass", false, false) INITIALIZE_PASS_END(AArch64ConditionOptimizer
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
void updateTerminator()
Update the terminator instructions in block to account for changes to the layout. ...
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createAArch64ConditionOptimizerPass()
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
void initializeAArch64ConditionOptimizerPass(PassRegistry &)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
LLVM_NODISCARD bool empty() const
APFloat abs(APFloat X)
Returns the absolute value of the argument.
static AArch64CC::CondCode getAdjustedCmp(AArch64CC::CondCode Cmp)
static bool parseCond(ArrayRef< MachineOperand > Cond, AArch64CC::CondCode &CC)
iterator_range< df_iterator< T > > depth_first(const T &G)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef - Represent a constant reference to a string, i.e.
const MachineOperand & getOperand(unsigned i) const
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...