diff options
Diffstat (limited to 'llvm/lib/CodeGen/SelectOptimize.cpp')
-rw-r--r-- | llvm/lib/CodeGen/SelectOptimize.cpp | 82 |
1 files changed, 64 insertions, 18 deletions
diff --git a/llvm/lib/CodeGen/SelectOptimize.cpp b/llvm/lib/CodeGen/SelectOptimize.cpp index 2e03ae6..0a5f0a8 100644 --- a/llvm/lib/CodeGen/SelectOptimize.cpp +++ b/llvm/lib/CodeGen/SelectOptimize.cpp @@ -130,7 +130,11 @@ public: class SelectLike { SelectLike(Instruction *I) : I(I) {} + /// The select (/or) instruction. Instruction *I; + /// Whether this select is inverted, "not(cond), FalseVal, TrueVal", as + /// opposed to the original condition. + bool Inverted = false; public: /// Match a select or select-like instruction, returning a SelectLike. @@ -153,14 +157,22 @@ public: bool isValid() { return I; } operator bool() { return isValid(); } + /// Invert the select by inverting the condition and switching the operands. + void setInverted() { + assert(!Inverted && "Trying to invert an inverted SelectLike"); + assert(isa<Instruction>(getCondition()) && + cast<Instruction>(getCondition())->getOpcode() == + Instruction::Xor); + Inverted = true; + } + bool isInverted() const { return Inverted; } + Instruction *getI() { return I; } const Instruction *getI() const { return I; } Type *getType() const { return I->getType(); } - /// Return the condition for the SelectLike instruction. For example the - /// condition of a select or c in `or(zext(c), x)` - Value *getCondition() const { + Value *getNonInvertedCondition() const { if (auto *Sel = dyn_cast<SelectInst>(I)) return Sel->getCondition(); // Or(zext) case @@ -177,11 +189,24 @@ public: llvm_unreachable("Unhandled case in getCondition"); } + /// Return the condition for the SelectLike instruction. For example the + /// condition of a select or c in `or(zext(c), x)` + Value *getCondition() const { + Value *CC = getNonInvertedCondition(); + // For inverted conditions the CC is checked when created to be a not + // (xor) instruction. + if (Inverted) + return cast<Instruction>(CC)->getOperand(0); + return CC; + } + /// Return the true value for the SelectLike instruction. Note this may not /// exist for all SelectLike instructions. For example, for `or(zext(c), x)` /// the true value would be `or(x,1)`. As this value does not exist, nullptr /// is returned. - Value *getTrueValue() const { + Value *getTrueValue(bool HonorInverts = true) const { + if (Inverted && HonorInverts) + return getFalseValue(/*HonorInverts=*/false); if (auto *Sel = dyn_cast<SelectInst>(I)) return Sel->getTrueValue(); // Or(zext) case - The true value is Or(X), so return nullptr as the value @@ -195,7 +220,9 @@ public: /// Return the false value for the SelectLike instruction. For example the /// getFalseValue of a select or `x` in `or(zext(c), x)` (which is /// `select(c, x|1, x)`) - Value *getFalseValue() const { + Value *getFalseValue(bool HonorInverts = true) const { + if (Inverted && HonorInverts) + return getTrueValue(/*HonorInverts=*/false); if (auto *Sel = dyn_cast<SelectInst>(I)) return Sel->getFalseValue(); // Or(zext) case - return the operand which is not the zext. @@ -216,8 +243,8 @@ public: /// InstCostMap. This may need to be generated for select-like instructions. Scaled64 getTrueOpCost(DenseMap<const Instruction *, CostInfo> &InstCostMap, const TargetTransformInfo *TTI) { - if (auto *Sel = dyn_cast<SelectInst>(I)) - if (auto *I = dyn_cast<Instruction>(Sel->getTrueValue())) + if (isa<SelectInst>(I)) + if (auto *I = dyn_cast<Instruction>(getTrueValue())) return InstCostMap.contains(I) ? InstCostMap[I].NonPredCost : Scaled64::getZero(); @@ -242,8 +269,8 @@ public: Scaled64 getFalseOpCost(DenseMap<const Instruction *, CostInfo> &InstCostMap, const TargetTransformInfo *TTI) { - if (auto *Sel = dyn_cast<SelectInst>(I)) - if (auto *I = dyn_cast<Instruction>(Sel->getFalseValue())) + if (isa<SelectInst>(I)) + if (auto *I = dyn_cast<Instruction>(getFalseValue())) return InstCostMap.contains(I) ? InstCostMap[I].NonPredCost : Scaled64::getZero(); @@ -510,9 +537,10 @@ getTrueOrFalseValue(SelectOptimizeImpl::SelectLike SI, bool isTrue, for (SelectInst *DefSI = dyn_cast<SelectInst>(SI.getI()); DefSI != nullptr && Selects.count(DefSI); DefSI = dyn_cast<SelectInst>(V)) { - assert(DefSI->getCondition() == SI.getCondition() && - "The condition of DefSI does not match with SI"); - V = (isTrue ? DefSI->getTrueValue() : DefSI->getFalseValue()); + if (DefSI->getCondition() == SI.getCondition()) + V = (isTrue ? DefSI->getTrueValue() : DefSI->getFalseValue()); + else // Handle inverted SI + V = (!isTrue ? DefSI->getTrueValue() : DefSI->getFalseValue()); } if (isa<BinaryOperator>(SI.getI())) { @@ -632,18 +660,19 @@ void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) { // Delete the unconditional branch that was just created by the split. StartBlock->getTerminator()->eraseFromParent(); - // Move any debug/pseudo instructions that were in-between the select - // group to the newly-created end block. - SmallVector<Instruction *, 2> DebugPseudoINS; + // Move any debug/pseudo instructions and not's that were in-between the + // select group to the newly-created end block. + SmallVector<Instruction *, 2> SinkInstrs; auto DIt = SI.getI()->getIterator(); while (&*DIt != LastSI.getI()) { if (DIt->isDebugOrPseudoInst()) - DebugPseudoINS.push_back(&*DIt); + SinkInstrs.push_back(&*DIt); + if (match(&*DIt, m_Not(m_Specific(SI.getCondition())))) + SinkInstrs.push_back(&*DIt); DIt++; } - for (auto *DI : DebugPseudoINS) { + for (auto *DI : SinkInstrs) DI->moveBeforePreserving(&*EndBlock->getFirstInsertionPt()); - } // Duplicate implementation for DbgRecords, the non-instruction debug-info // format. Helper lambda for moving DbgRecords to the end block. @@ -765,6 +794,13 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB, ++BBIt; continue; } + + // Skip not(select(..)), if the not is part of the same select group + if (match(NI, m_Not(m_Specific(SI.getCondition())))) { + ++BBIt; + continue; + } + // We only allow selects in the same group, not other select-like // instructions. if (!isa<SelectInst>(NI)) @@ -773,6 +809,10 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB, SelectLike NSI = SelectLike::match(NI); if (NSI && SI.getCondition() == NSI.getCondition()) { SIGroup.push_back(NSI); + } else if (NSI && match(NSI.getCondition(), + m_Not(m_Specific(SI.getCondition())))) { + NSI.setInverted(); + SIGroup.push_back(NSI); } else break; ++BBIt; @@ -783,6 +823,12 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB, if (!isSelectKindSupported(SI)) continue; + LLVM_DEBUG({ + dbgs() << "New Select group with\n"; + for (auto SI : SIGroup) + dbgs() << " " << *SI.getI() << "\n"; + }); + SIGroups.push_back(SIGroup); } } |