summaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/IPO/Inliner.cpp2
-rw-r--r--lib/Transforms/IPO/MergeFunctions.cpp5
-rw-r--r--lib/Transforms/InstCombine/InstCombineAndOrXor.cpp19
-rw-r--r--lib/Transforms/InstCombine/InstCombineSelect.cpp28
-rw-r--r--lib/Transforms/Scalar/LoopStrengthReduce.cpp11
-rw-r--r--lib/Transforms/Utils/Local.cpp5
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp71
7 files changed, 131 insertions, 10 deletions
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp
index 027a220..9bb01f5 100644
--- a/lib/Transforms/IPO/Inliner.cpp
+++ b/lib/Transforms/IPO/Inliner.cpp
@@ -399,7 +399,7 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC) {
// We can only inline direct calls to non-declarations.
if (Callee == 0 || Callee->isDeclaration()) continue;
- // If this call sites was obtained by inlining another function, verify
+ // If this call site was obtained by inlining another function, verify
// that the include path for the function did not include the callee
// itself. If so, we'd be recursively inlinling the same function,
// which would provide the same callsites, which would cause us to
diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp
index 55d5e2a..aeeafe7 100644
--- a/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/lib/Transforms/IPO/MergeFunctions.cpp
@@ -603,6 +603,10 @@ static void ThunkGToF(Function *F, Function *G) {
}
static void AliasGToF(Function *F, Function *G) {
+ // Darwin will trigger llvm_unreachable if asked to codegen an alias.
+ return ThunkGToF(F, G);
+
+#if 0
if (!G->hasExternalLinkage() && !G->hasLocalLinkage() && !G->hasWeakLinkage())
return ThunkGToF(F, G);
@@ -614,6 +618,7 @@ static void AliasGToF(Function *F, Function *G) {
GA->setVisibility(G->getVisibility());
G->replaceAllUsesWith(GA);
G->eraseFromParent();
+#endif
}
static bool fold(std::vector<Function *> &FnVec, unsigned i, unsigned j) {
diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 3f4a857..5876f40 100644
--- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -472,6 +472,25 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
Value *NewOr = Builder->CreateOr(Val, Val2);
return Builder->CreateICmp(LHSCC, NewOr, LHSCst);
}
+
+ // (icmp ne (A & C1), 0) & (icmp ne (A & C2), 0) -->
+ // (icmp eq (A & (C1|C2)), (C1|C2))
+ if (LHSCC == ICmpInst::ICMP_NE && LHSCst->isZero()) {
+ Instruction *I1 = dyn_cast<Instruction>(Val);
+ Instruction *I2 = dyn_cast<Instruction>(Val2);
+ if (I1 && I1->getOpcode() == Instruction::And &&
+ I2 && I2->getOpcode() == Instruction::And &&
+ I1->getOperand(0) == I1->getOperand(0)) {
+ ConstantInt *CI1 = dyn_cast<ConstantInt>(I1->getOperand(1));
+ ConstantInt *CI2 = dyn_cast<ConstantInt>(I2->getOperand(1));
+ if (CI1 && !CI1->isZero() && CI2 && !CI2->isZero() &&
+ CI1->getValue().operator&(CI2->getValue()) == 0) {
+ Constant *ConstOr = ConstantExpr::getOr(CI1, CI2);
+ Value *NewAnd = Builder->CreateAnd(I1->getOperand(0), ConstOr);
+ return Builder->CreateICmp(ICmpInst::ICMP_EQ, NewAnd, ConstOr);
+ }
+ }
+ }
}
// From here on, we only handle:
diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp
index c44fe9d..f9ffdb1 100644
--- a/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -699,6 +699,34 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
SI.setOperand(2, TrueVal);
return &SI;
}
+
+ // select (A == 0 | B == 0), T, F--> select (A != 0 & B != 0), F, T
+ // Note: This is a canonicalization rather than an optimization, and is used
+ // to expose opportunities to other instcombine transforms.
+ Instruction* CondInst = dyn_cast<Instruction>(CondVal);
+ if (CondInst && CondInst->hasOneUse() &&
+ CondInst->getOpcode() == Instruction::Or) {
+ ICmpInst *LHSCmp = dyn_cast<ICmpInst>(CondInst->getOperand(0));
+ ICmpInst *RHSCmp = dyn_cast<ICmpInst>(CondInst->getOperand(1));
+ if (LHSCmp && LHSCmp->hasOneUse() &&
+ LHSCmp->getPredicate() == ICmpInst::ICMP_EQ &&
+ RHSCmp && RHSCmp->hasOneUse() &&
+ RHSCmp->getPredicate() == ICmpInst::ICMP_EQ) {
+ ConstantInt* C1 = dyn_cast<ConstantInt>(LHSCmp->getOperand(1));
+ ConstantInt* C2 = dyn_cast<ConstantInt>(RHSCmp->getOperand(1));
+ if (C1 && C1->isZero() && C2 && C2->isZero()) {
+ LHSCmp->setPredicate(ICmpInst::ICMP_NE);
+ RHSCmp->setPredicate(ICmpInst::ICMP_NE);
+ Value *And =
+ InsertNewInstBefore(BinaryOperator::CreateAnd(LHSCmp, RHSCmp,
+ "and."+CondVal->getName()), SI);
+ SI.setOperand(0, And);
+ SI.setOperand(1, FalseVal);
+ SI.setOperand(2, TrueVal);
+ return &SI;
+ }
+ }
+ }
return 0;
}
diff --git a/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index a250a88..1f9b415 100644
--- a/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -2362,7 +2362,7 @@ void LSRInstance::GenerateConstantOffsets(LSRUse &LU, unsigned LUIdx,
Formula Base) {
// TODO: For now, just add the min and max offset, because it usually isn't
// worthwhile looking at everything inbetween.
- SmallVector<int64_t, 4> Worklist;
+ SmallVector<int64_t, 2> Worklist;
Worklist.push_back(LU.MinOffset);
if (LU.MaxOffset != LU.MinOffset)
Worklist.push_back(LU.MaxOffset);
@@ -2376,7 +2376,14 @@ void LSRInstance::GenerateConstantOffsets(LSRUse &LU, unsigned LUIdx,
F.AM.BaseOffs = (uint64_t)Base.AM.BaseOffs - *I;
if (isLegalUse(F.AM, LU.MinOffset - *I, LU.MaxOffset - *I,
LU.Kind, LU.AccessTy, TLI)) {
- F.BaseRegs[i] = SE.getAddExpr(G, SE.getConstant(G->getType(), *I));
+ // Add the offset to the base register.
+ const SCEV *NewG = SE.getAddExpr(G, SE.getConstant(G->getType(), *I));
+ // If it cancelled out, drop the base register, otherwise update it.
+ if (NewG->isZero()) {
+ std::swap(F.BaseRegs[i], F.BaseRegs.back());
+ F.BaseRegs.pop_back();
+ } else
+ F.BaseRegs[i] = NewG;
(void)InsertFormula(LU, LUIdx, F);
}
diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp
index 0b48a8f..8e91138 100644
--- a/lib/Transforms/Utils/Local.cpp
+++ b/lib/Transforms/Utils/Local.cpp
@@ -306,7 +306,7 @@ bool llvm::SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD) {
WeakVH BIHandle(BI);
ReplaceAndSimplifyAllUses(Inst, V, TD);
MadeChange = true;
- if (BIHandle == 0)
+ if (BIHandle != BI)
BI = BB->begin();
continue;
}
@@ -354,12 +354,13 @@ void llvm::RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
// value into all of its uses.
assert(PNV != PN && "hasConstantValue broken");
+ Value *OldPhiIt = PhiIt;
ReplaceAndSimplifyAllUses(PN, PNV, TD);
// If recursive simplification ended up deleting the next PHI node we would
// iterate to, then our iterator is invalid, restart scanning from the top
// of the block.
- if (PhiIt == 0) PhiIt = &BB->front();
+ if (PhiIt != OldPhiIt) PhiIt = &BB->front();
}
}
diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp
index fd3ed3e..27b07d9 100644
--- a/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -1377,8 +1377,9 @@ static bool SimplifyCondBranchToTwoReturns(BranchInst *BI) {
bool llvm::FoldBranchToCommonDest(BranchInst *BI) {
BasicBlock *BB = BI->getParent();
Instruction *Cond = dyn_cast<Instruction>(BI->getCondition());
- if (Cond == 0) return false;
-
+ if (Cond == 0 || (!isa<CmpInst>(Cond) && !isa<BinaryOperator>(Cond)) ||
+ Cond->getParent() != BB || !Cond->hasOneUse())
+ return false;
// Only allow this if the condition is a simple instruction that can be
// executed unconditionally. It must be in the same block as the branch, and
@@ -1387,11 +1388,23 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) {
// Ignore dbg intrinsics.
while(isa<DbgInfoIntrinsic>(FrontIt))
++FrontIt;
- if ((!isa<CmpInst>(Cond) && !isa<BinaryOperator>(Cond)) ||
- Cond->getParent() != BB || &*FrontIt != Cond || !Cond->hasOneUse()) {
- return false;
+
+ // Allow a single instruction to be hoisted in addition to the compare
+ // that feeds the branch. We later ensure that any values that _it_ uses
+ // were also live in the predecessor, so that we don't unnecessarily create
+ // register pressure or inhibit out-of-order execution.
+ Instruction *BonusInst = 0;
+ if (&*FrontIt != Cond &&
+ FrontIt->hasOneUse() && *FrontIt->use_begin() == Cond &&
+ FrontIt->isSafeToSpeculativelyExecute()) {
+ BonusInst = &*FrontIt;
+ ++FrontIt;
}
+ // Only a single bonus inst is allowed.
+ if (&*FrontIt != Cond)
+ return false;
+
// Make sure the instruction after the condition is the cond branch.
BasicBlock::iterator CondIt = Cond; ++CondIt;
// Ingore dbg intrinsics.
@@ -1429,6 +1442,44 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) {
!SafeToMergeTerminators(BI, PBI))
continue;
+ // Ensure that any values used in the bonus instruction are also used
+ // by the terminator of the predecessor. This means that those values
+ // must already have been resolved, so we won't be inhibiting the
+ // out-of-order core by speculating them earlier.
+ if (BonusInst) {
+ // Collect the values used by the bonus inst
+ SmallPtrSet<Value*, 4> UsedValues;
+ for (Instruction::op_iterator OI = BonusInst->op_begin(),
+ OE = BonusInst->op_end(); OI != OE; ++OI) {
+ Value* V = *OI;
+ if (!isa<Constant>(V))
+ UsedValues.insert(V);
+ }
+
+ SmallVector<std::pair<Value*, unsigned>, 4> Worklist;
+ Worklist.push_back(std::make_pair(PBI->getOperand(0), 0));
+
+ // Walk up to four levels back up the use-def chain of the predecessor's
+ // terminator to see if all those values were used. The choice of four
+ // levels is arbitrary, to provide a compile-time-cost bound.
+ while (!Worklist.empty()) {
+ std::pair<Value*, unsigned> Pair = Worklist.back();
+ Worklist.pop_back();
+
+ if (Pair.second >= 4) continue;
+ UsedValues.erase(Pair.first);
+ if (UsedValues.empty()) break;
+
+ if (Instruction* I = dyn_cast<Instruction>(Pair.first)) {
+ for (Instruction::op_iterator OI = I->op_begin(), OE = I->op_end();
+ OI != OE; ++OI)
+ Worklist.push_back(std::make_pair(OI->get(), Pair.second+1));
+ }
+ }
+
+ if (!UsedValues.empty()) return false;
+ }
+
Instruction::BinaryOps Opc;
bool InvertPredCond = false;
@@ -1457,9 +1508,19 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) {
PBI->setSuccessor(1, OldTrue);
}
+ // If we have a bonus inst, clone it into the predecessor block.
+ Instruction *NewBonus = 0;
+ if (BonusInst) {
+ NewBonus = BonusInst->clone();
+ PredBlock->getInstList().insert(PBI, NewBonus);
+ NewBonus->takeName(BonusInst);
+ BonusInst->setName(BonusInst->getName()+".old");
+ }
+
// Clone Cond into the predecessor basic block, and or/and the
// two conditions together.
Instruction *New = Cond->clone();
+ if (BonusInst) New->replaceUsesOfWith(BonusInst, NewBonus);
PredBlock->getInstList().insert(PBI, New);
New->takeName(Cond);
Cond->setName(New->getName()+".old");
OpenPOWER on IntegriCloud