82 #define DEBUG_TYPE "aarch64-condopt"
84 STATISTIC(NumConditionsAdjusted,
"Number of conditions adjusted");
95 typedef std::tuple<int, unsigned, AArch64CC::CondCode> CmpInfo;
102 void modifyCmp(
MachineInstr *CmpMI,
const CmpInfo &Info);
106 const char *getPassName()
const override {
107 return "AArch64 Condition Optimizer";
119 "AArch64 CondOpt Pass",
false,
false)
125 return new AArch64ConditionOptimizer();
128 void AArch64ConditionOptimizer::getAnalysisUsage(
AnalysisUsage &AU)
const {
137 MachineInstr *AArch64ConditionOptimizer::findSuitableCompare(
143 if (I->getOpcode() != AArch64::Bcc)
149 assert(!I->isTerminator() &&
"Spurious terminator");
150 switch (I->getOpcode()) {
152 case AArch64::SUBSWri:
153 case AArch64::SUBSXri:
155 case AArch64::ADDSWri:
156 case AArch64::ADDSXri:
157 if (MRI->use_empty(I->getOperand(0).getReg()))
160 DEBUG(
dbgs() <<
"Destination of cmp is not dead, " << *I <<
'\n');
169 case AArch64::FCMPDri:
170 case AArch64::FCMPSri:
171 case AArch64::FCMPESri:
172 case AArch64::FCMPEDri:
174 case AArch64::SUBSWrr:
175 case AArch64::SUBSXrr:
176 case AArch64::ADDSWrr:
177 case AArch64::ADDSXrr:
178 case AArch64::FCMPSrr:
179 case AArch64::FCMPDrr:
180 case AArch64::FCMPESrr:
181 case AArch64::FCMPEDrr:
193 case AArch64::ADDSWri:
return AArch64::SUBSWri;
194 case AArch64::ADDSXri:
return AArch64::SUBSXri;
195 case AArch64::SUBSWri:
return AArch64::ADDSWri;
196 case AArch64::SUBSXri:
return AArch64::ADDSXri;
216 AArch64ConditionOptimizer::CmpInfo AArch64ConditionOptimizer::adjustCmp(
222 bool Negative = (Opc == AArch64::ADDSWri || Opc == AArch64::ADDSXri);
227 Correction = -Correction;
231 const int NewImm =
std::abs(OldImm + Correction);
235 if (OldImm == 0 && ((Negative && Correction == 1) ||
236 (!Negative && Correction == -1))) {
244 void AArch64ConditionOptimizer::modifyCmp(
MachineInstr *CmpMI,
245 const CmpInfo &Info) {
249 std::tie(Imm, Opc, Cmp) = Info;
273 ++NumConditionsAdjusted;
281 if (Cond[0].getImm() != -1) {
282 assert(Cond.
size() == 1 &&
"Unknown Cond array format");
292 bool AArch64ConditionOptimizer::adjustTo(
MachineInstr *CmpMI,
295 CmpInfo Info = adjustCmp(CmpMI, Cmp);
296 if (std::get<0>(Info) == ToImm && std::get<1>(Info) == To->
getOpcode()) {
297 modifyCmp(CmpMI, Info);
303 bool AArch64ConditionOptimizer::runOnMachineFunction(
MachineFunction &MF) {
304 DEBUG(
dbgs() <<
"********** AArch64 Conditional Compares **********\n"
305 <<
"********** Function: " << MF.
getName() <<
'\n');
307 DomTree = &getAnalysis<MachineDominatorTree>();
310 bool Changed =
false;
322 if (TII->AnalyzeBranch(*HBB, TBB, FBB, HeadCond)) {
327 if (!TBB || TBB == HBB) {
333 if (TII->AnalyzeBranch(*TBB, TBB_TBB, TBB_FBB, TrueCond)) {
363 DEBUG(
dbgs() <<
"\timmediate: " << HeadImm <<
'\n');
368 DEBUG(
dbgs() <<
"\timmediate: " << TrueImm <<
'\n');
383 CmpInfo HeadCmpInfo = adjustCmp(HeadCmpMI, HeadCmp);
384 CmpInfo TrueCmpInfo = adjustCmp(TrueCmpMI, TrueCmp);
385 if (std::get<0>(HeadCmpInfo) == std::get<0>(TrueCmpInfo) &&
386 std::get<1>(HeadCmpInfo) == std::get<1>(TrueCmpInfo)) {
387 modifyCmp(HeadCmpMI, HeadCmpInfo);
388 modifyCmp(TrueCmpMI, TrueCmpInfo);
406 bool adjustHeadCond = (HeadImm < TrueImm);
408 adjustHeadCond = !adjustHeadCond;
411 if (adjustHeadCond) {
412 Changed |= adjustTo(HeadCmpMI, HeadCmp, TrueCmpMI, TrueImm);
414 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.
STATISTIC(NumFunctions,"Total number of functions")
int getNumber() const
getNumber - MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a M...
iterator getFirstTerminator()
getFirstTerminator - returns an iterator to the first terminator instruction of this basic block...
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
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
static const char * getCondCodeName(CondCode Code)
bool LLVM_ATTRIBUTE_UNUSED_RESULT 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)...
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.
bundle_iterator< MachineInstr, instr_iterator > iterator
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.
FunctionPass class - This class is used to implement most global optimizations.
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
BuildMI - Builder interface.
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()
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)
virtual const TargetInstrInfo * getInstrInfo() const
const MachineInstrBuilder & addOperand(const MachineOperand &MO) const
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
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...