Add a if-conversion optimization that allows 'true' side of a diamond to be
unpredicated. That is, turn subeq r0, r1, #1 addne r0, r1, #1 into sub r0, r1, #1 addne r0, r1, #1 For targets where conditional instructions are always executed, this may be beneficial. It may remove pseudo anti-dependency in out-of-order execution CPUs. e.g. op r1, ... str r1, [r10] ; end-of-life of r1 as div result cmp r0, #65 movne r1, #44 ; raw dependency on previous r1 moveq r1, #12 If movne is unpredicated, then op r1, ... str r1, [r10] cmp r0, #65 mov r1, #44 ; r1 written unconditionally moveq r1, #12 Both mov and moveq are no longer depdendent on the first instruction. This gives the out-of-order execution engine more freedom to reorder them. This has passed entire LLVM test suite. But it has not been enabled for any ARM variant pending more performance evaluation. rdar://8951196 llvm-svn: 146914
This commit is contained in:
parent
6dbc17dffe
commit
4266a79351
|
@ -353,6 +353,22 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// isProfitableToUnpredicate - Return true if it's profitable to unpredicate
|
||||||
|
/// one side of a 'diamond', i.e. two sides of if-else predicated on mutually
|
||||||
|
/// exclusive predicates.
|
||||||
|
/// e.g.
|
||||||
|
/// subeq r0, r1, #1
|
||||||
|
/// addne r0, r1, #1
|
||||||
|
/// =>
|
||||||
|
/// sub r0, r1, #1
|
||||||
|
/// addne r0, r1, #1
|
||||||
|
///
|
||||||
|
/// This may be profitable is conditional instructions are always executed.
|
||||||
|
virtual bool isProfitableToUnpredicate(MachineBasicBlock &TMBB,
|
||||||
|
MachineBasicBlock &FMBB) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/// copyPhysReg - Emit instructions to copy a pair of physical registers.
|
/// copyPhysReg - Emit instructions to copy a pair of physical registers.
|
||||||
virtual void copyPhysReg(MachineBasicBlock &MBB,
|
virtual void copyPhysReg(MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator MI, DebugLoc DL,
|
MachineBasicBlock::iterator MI, DebugLoc DL,
|
||||||
|
|
|
@ -62,6 +62,7 @@ STATISTIC(NumTriangleFRev, "Number of triangle (F/R) if-conversions performed");
|
||||||
STATISTIC(NumDiamonds, "Number of diamond if-conversions performed");
|
STATISTIC(NumDiamonds, "Number of diamond if-conversions performed");
|
||||||
STATISTIC(NumIfConvBBs, "Number of if-converted blocks");
|
STATISTIC(NumIfConvBBs, "Number of if-converted blocks");
|
||||||
STATISTIC(NumDupBBs, "Number of duplicated blocks");
|
STATISTIC(NumDupBBs, "Number of duplicated blocks");
|
||||||
|
STATISTIC(NumUnpred, "Number of true blocks of diamonds unpredicated");
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class IfConverter : public MachineFunctionPass {
|
class IfConverter : public MachineFunctionPass {
|
||||||
|
@ -195,7 +196,8 @@ namespace {
|
||||||
void PredicateBlock(BBInfo &BBI,
|
void PredicateBlock(BBInfo &BBI,
|
||||||
MachineBasicBlock::iterator E,
|
MachineBasicBlock::iterator E,
|
||||||
SmallVectorImpl<MachineOperand> &Cond,
|
SmallVectorImpl<MachineOperand> &Cond,
|
||||||
SmallSet<unsigned, 4> &Redefs);
|
SmallSet<unsigned, 4> &Redefs,
|
||||||
|
SmallSet<unsigned, 4> *LaterRedefs = 0);
|
||||||
void CopyAndPredicateBlock(BBInfo &ToBBI, BBInfo &FromBBI,
|
void CopyAndPredicateBlock(BBInfo &ToBBI, BBInfo &FromBBI,
|
||||||
SmallVectorImpl<MachineOperand> &Cond,
|
SmallVectorImpl<MachineOperand> &Cond,
|
||||||
SmallSet<unsigned, 4> &Redefs,
|
SmallSet<unsigned, 4> &Redefs,
|
||||||
|
@ -1280,7 +1282,7 @@ bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
|
||||||
BBI.BB->splice(BBI.BB->end(), BBI1->BB, BBI1->BB->begin(), DI1);
|
BBI.BB->splice(BBI.BB->end(), BBI1->BB, BBI1->BB->begin(), DI1);
|
||||||
BBI2->BB->erase(BBI2->BB->begin(), DI2);
|
BBI2->BB->erase(BBI2->BB->begin(), DI2);
|
||||||
|
|
||||||
// Predicate the 'true' block after removing its branch.
|
// Remove branch from 'true' block and remove duplicated instructions.
|
||||||
BBI1->NonPredSize -= TII->RemoveBranch(*BBI1->BB);
|
BBI1->NonPredSize -= TII->RemoveBranch(*BBI1->BB);
|
||||||
DI1 = BBI1->BB->end();
|
DI1 = BBI1->BB->end();
|
||||||
for (unsigned i = 0; i != NumDups2; ) {
|
for (unsigned i = 0; i != NumDups2; ) {
|
||||||
|
@ -1293,9 +1295,8 @@ bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
BBI1->BB->erase(DI1, BBI1->BB->end());
|
BBI1->BB->erase(DI1, BBI1->BB->end());
|
||||||
PredicateBlock(*BBI1, BBI1->BB->end(), *Cond1, Redefs);
|
|
||||||
|
|
||||||
// Predicate the 'false' block.
|
// Remove 'false' block branch and find the last instruction to predicate.
|
||||||
BBI2->NonPredSize -= TII->RemoveBranch(*BBI2->BB);
|
BBI2->NonPredSize -= TII->RemoveBranch(*BBI2->BB);
|
||||||
DI2 = BBI2->BB->end();
|
DI2 = BBI2->BB->end();
|
||||||
while (NumDups2 != 0) {
|
while (NumDups2 != 0) {
|
||||||
|
@ -1307,6 +1308,55 @@ bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
|
||||||
if (!DI2->isDebugValue())
|
if (!DI2->isDebugValue())
|
||||||
--NumDups2;
|
--NumDups2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remember which registers would later be defined by the false block.
|
||||||
|
// This allows us not to predicate instructions in the true block that would
|
||||||
|
// later be re-defined. That is, rather than
|
||||||
|
// subeq r0, r1, #1
|
||||||
|
// addne r0, r1, #1
|
||||||
|
// generate:
|
||||||
|
// sub r0, r1, #1
|
||||||
|
// addne r0, r1, #1
|
||||||
|
SmallSet<unsigned, 4> RedefsByFalse;
|
||||||
|
SmallSet<unsigned, 4> ExtUses;
|
||||||
|
if (TII->isProfitableToUnpredicate(*BBI1->BB, *BBI2->BB)) {
|
||||||
|
for (MachineBasicBlock::iterator FI = BBI2->BB->begin(); FI != DI2; ++FI) {
|
||||||
|
if (FI->isDebugValue())
|
||||||
|
continue;
|
||||||
|
SmallVector<unsigned, 4> Defs;
|
||||||
|
for (unsigned i = 0, e = FI->getNumOperands(); i != e; ++i) {
|
||||||
|
const MachineOperand &MO = FI->getOperand(i);
|
||||||
|
if (!MO.isReg())
|
||||||
|
continue;
|
||||||
|
unsigned Reg = MO.getReg();
|
||||||
|
if (!Reg)
|
||||||
|
continue;
|
||||||
|
if (MO.isDef()) {
|
||||||
|
Defs.push_back(Reg);
|
||||||
|
} else if (!RedefsByFalse.count(Reg)) {
|
||||||
|
// These are defined before ctrl flow reach the 'false' instructions.
|
||||||
|
// They cannot be modified by the 'true' instructions.
|
||||||
|
ExtUses.insert(Reg);
|
||||||
|
for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR)
|
||||||
|
ExtUses.insert(*SR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = Defs.size(); i != e; ++i) {
|
||||||
|
unsigned Reg = Defs[i];
|
||||||
|
if (!ExtUses.count(Reg)) {
|
||||||
|
RedefsByFalse.insert(Reg);
|
||||||
|
for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR)
|
||||||
|
RedefsByFalse.insert(*SR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Predicate the 'true' block.
|
||||||
|
PredicateBlock(*BBI1, BBI1->BB->end(), *Cond1, Redefs, &RedefsByFalse);
|
||||||
|
|
||||||
|
// Predicate the 'false' block.
|
||||||
PredicateBlock(*BBI2, DI2, *Cond2, Redefs);
|
PredicateBlock(*BBI2, DI2, *Cond2, Redefs);
|
||||||
|
|
||||||
// Merge the true block into the entry of the diamond.
|
// Merge the true block into the entry of the diamond.
|
||||||
|
@ -1355,15 +1405,49 @@ bool IfConverter::IfConvertDiamond(BBInfo &BBI, IfcvtKind Kind,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool MaySpeculate(const MachineInstr *MI,
|
||||||
|
SmallSet<unsigned, 4> &LaterRedefs,
|
||||||
|
const TargetInstrInfo *TII) {
|
||||||
|
bool SawStore = true;
|
||||||
|
if (!MI->isSafeToMove(TII, 0, SawStore))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
|
const MachineOperand &MO = MI->getOperand(i);
|
||||||
|
if (!MO.isReg())
|
||||||
|
continue;
|
||||||
|
unsigned Reg = MO.getReg();
|
||||||
|
if (!Reg)
|
||||||
|
continue;
|
||||||
|
if (MO.isDef() && !LaterRedefs.count(Reg))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// PredicateBlock - Predicate instructions from the start of the block to the
|
/// PredicateBlock - Predicate instructions from the start of the block to the
|
||||||
/// specified end with the specified condition.
|
/// specified end with the specified condition.
|
||||||
void IfConverter::PredicateBlock(BBInfo &BBI,
|
void IfConverter::PredicateBlock(BBInfo &BBI,
|
||||||
MachineBasicBlock::iterator E,
|
MachineBasicBlock::iterator E,
|
||||||
SmallVectorImpl<MachineOperand> &Cond,
|
SmallVectorImpl<MachineOperand> &Cond,
|
||||||
SmallSet<unsigned, 4> &Redefs) {
|
SmallSet<unsigned, 4> &Redefs,
|
||||||
|
SmallSet<unsigned, 4> *LaterRedefs) {
|
||||||
|
bool AnyUnpred = false;
|
||||||
|
bool MaySpec = LaterRedefs != 0;
|
||||||
for (MachineBasicBlock::iterator I = BBI.BB->begin(); I != E; ++I) {
|
for (MachineBasicBlock::iterator I = BBI.BB->begin(); I != E; ++I) {
|
||||||
if (I->isDebugValue() || TII->isPredicated(I))
|
if (I->isDebugValue() || TII->isPredicated(I))
|
||||||
continue;
|
continue;
|
||||||
|
// It may be possible not to predicate an instruction if it's the 'true'
|
||||||
|
// side of a diamond and the 'false' side may re-define the instruction's
|
||||||
|
// defs.
|
||||||
|
if (MaySpec && MaySpeculate(I, *LaterRedefs, TII)) {
|
||||||
|
AnyUnpred = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// If any instruction is predicated, then every instruction after it must
|
||||||
|
// be predicated.
|
||||||
|
MaySpec = false;
|
||||||
if (!TII->PredicateInstruction(I, Cond)) {
|
if (!TII->PredicateInstruction(I, Cond)) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
dbgs() << "Unable to predicate " << *I << "!\n";
|
dbgs() << "Unable to predicate " << *I << "!\n";
|
||||||
|
@ -1382,6 +1466,8 @@ void IfConverter::PredicateBlock(BBInfo &BBI,
|
||||||
BBI.NonPredSize = 0;
|
BBI.NonPredSize = 0;
|
||||||
|
|
||||||
++NumIfConvBBs;
|
++NumIfConvBBs;
|
||||||
|
if (AnyUnpred)
|
||||||
|
++NumUnpred;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CopyAndPredicateBlock - Copy and predicate instructions from source BB to
|
/// CopyAndPredicateBlock - Copy and predicate instructions from source BB to
|
||||||
|
|
Loading…
Reference in New Issue