82 #define DEBUG_TYPE "aarch64-condopt"
84 STATISTIC(NumConditionsAdjusted,
"Number of conditions adjusted");
95 typedef std::tuple<int, unsigned, AArch64CC::CondCode> CmpInfo;
104 void modifyCmp(
MachineInstr *CmpMI,
const CmpInfo &Info);
109 return "AArch64 Condition Optimizer";
117 "AArch64 CondOpt Pass",
false,
false)
123 return new AArch64ConditionOptimizer();
126 void AArch64ConditionOptimizer::getAnalysisUsage(
AnalysisUsage &AU)
const {
135 MachineInstr *AArch64ConditionOptimizer::findSuitableCompare(
141 if (I->getOpcode() != AArch64::Bcc)
146 if (SuccBB->isLiveIn(AArch64::NZCV))
152 assert(!I->isTerminator() &&
"Spurious terminator");
154 if (I->readsRegister(AArch64::NZCV))
156 switch (I->getOpcode()) {
158 case AArch64::SUBSWri:
159 case AArch64::SUBSXri:
161 case AArch64::ADDSWri:
162 case AArch64::ADDSXri: {
164 if (!I->getOperand(2).isImm()) {
165 DEBUG(
dbgs() <<
"Immediate of cmp is symbolic, " << *I <<
'\n');
167 }
else if (I->getOperand(2).getImm() << ShiftAmt >= 0xfff) {
168 DEBUG(
dbgs() <<
"Immediate of cmp may be out of range, " << *I <<
'\n');
170 }
else if (!
MRI->use_empty(I->getOperand(0).getReg())) {
171 DEBUG(
dbgs() <<
"Destination of cmp is not dead, " << *I <<
'\n');
182 case AArch64::FCMPDri:
183 case AArch64::FCMPSri:
184 case AArch64::FCMPESri:
185 case AArch64::FCMPEDri:
187 case AArch64::SUBSWrr:
188 case AArch64::SUBSXrr:
189 case AArch64::ADDSWrr:
190 case AArch64::ADDSXrr:
191 case AArch64::FCMPSrr:
192 case AArch64::FCMPDrr:
193 case AArch64::FCMPESrr:
194 case AArch64::FCMPEDrr:
206 case AArch64::ADDSWri:
return AArch64::SUBSWri;
207 case AArch64::ADDSXri:
return AArch64::SUBSXri;
208 case AArch64::SUBSWri:
return AArch64::ADDSWri;
209 case AArch64::SUBSXri:
return AArch64::ADDSXri;
229 AArch64ConditionOptimizer::CmpInfo AArch64ConditionOptimizer::adjustCmp(
235 bool Negative = (Opc == AArch64::ADDSWri || Opc == AArch64::ADDSXri);
240 Correction = -Correction;
244 const int NewImm =
std::abs(OldImm + Correction);
248 if (OldImm == 0 && ((Negative && Correction == 1) ||
249 (!Negative && Correction == -1))) {
257 void AArch64ConditionOptimizer::modifyCmp(
MachineInstr *CmpMI,
258 const CmpInfo &Info) {
262 std::tie(Imm, Opc, Cmp) = Info;
286 ++NumConditionsAdjusted;
294 if (Cond[0].getImm() != -1) {
295 assert(Cond.
size() == 1 &&
"Unknown Cond array format");
305 bool AArch64ConditionOptimizer::adjustTo(
MachineInstr *CmpMI,
308 CmpInfo Info = adjustCmp(CmpMI, Cmp);
309 if (std::get<0>(Info) == ToImm && std::get<1>(Info) == To->
getOpcode()) {
310 modifyCmp(CmpMI, Info);
316 bool AArch64ConditionOptimizer::runOnMachineFunction(
MachineFunction &MF) {
317 DEBUG(
dbgs() <<
"********** AArch64 Conditional Compares **********\n"
318 <<
"********** Function: " << MF.
getName() <<
'\n');
323 DomTree = &getAnalysis<MachineDominatorTree>();
326 bool Changed =
false;
343 if (!TBB || TBB == HBB) {
379 DEBUG(
dbgs() <<
"\timmediate: " << HeadImm <<
'\n');
384 DEBUG(
dbgs() <<
"\timmediate: " << TrueImm <<
'\n');
399 CmpInfo HeadCmpInfo = adjustCmp(HeadCmpMI, HeadCmp);
400 CmpInfo TrueCmpInfo = adjustCmp(TrueCmpMI, TrueCmp);
401 if (std::get<0>(HeadCmpInfo) == std::get<0>(TrueCmpInfo) &&
402 std::get<1>(HeadCmpInfo) == std::get<1>(TrueCmpInfo)) {
403 modifyCmp(HeadCmpMI, HeadCmpInfo);
404 modifyCmp(TrueCmpMI, TrueCmpInfo);
422 bool adjustHeadCond = (HeadImm < TrueImm);
424 adjustHeadCond = !adjustHeadCond;
427 if (adjustHeadCond) {
428 Changed |= adjustTo(HeadCmpMI, HeadCmp, TrueCmpMI, TrueImm);
430 Changed |= adjustTo(TrueCmpMI, TrueCmp, HeadCmpMI, HeadImm);
Pass interface - Implemented by all 'passes'.
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...
STATISTIC(NumFunctions,"Total number of functions")
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
iterator_range< succ_iterator > successors()
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
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)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
static const char * getCondCodeName(CondCode Code)
LLVM_NODISCARD bool empty() const
Base class for the actual dominator tree node.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
size_t size() const
size - Get the array size.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
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.
unsigned const MachineRegisterInfo * MRI
static int getComplementOpc(int Opc)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
aarch64 AArch64 CondOpt false
const MachineOperand & getOperand(unsigned i) const
Represent the analysis usage information of a pass.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE,"Assign register bank of generic virtual registers", false, false) RegBankSelect
FunctionPass class - This class is used to implement most global optimizations.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
INITIALIZE_PASS_BEGIN(AArch64ConditionOptimizer,"aarch64-condopt","AArch64 CondOpt Pass", false, false) INITIALIZE_PASS_END(AArch64ConditionOptimizer
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. ...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createAArch64ConditionOptimizerPass()
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
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.
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())
virtual const TargetInstrInfo * getInstrInfo() const
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
StringRef - Represent a constant reference to a string, i.e.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...