summaryrefslogtreecommitdiff
path: root/lib/Transforms/Scalar
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-11-01 07:13:54 +0000
committerChris Lattner <sabre@nondot.org>2006-11-01 07:13:54 +0000
commit76c731465048d5a888c48c7e98b7c425bd31c2b1 (patch)
tree1e1ff498c040b07d8da4b242c27c9b738f31003b /lib/Transforms/Scalar
parentacf7f2e3a9ade9660caad082be1e3b37bafd7f18 (diff)
downloadllvm-76c731465048d5a888c48c7e98b7c425bd31c2b1.tar.gz
llvm-76c731465048d5a888c48c7e98b7c425bd31c2b1.tar.bz2
llvm-76c731465048d5a888c48c7e98b7c425bd31c2b1.tar.xz
Turn a phi of many loads into a phi of the address and a single load of the
result. This can significantly shrink code and exposes identities more aggressively. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31344 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar')
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp71
1 files changed, 30 insertions, 41 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 250b760262..b9ce08697c 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -6833,6 +6833,19 @@ Instruction *InstCombiner::FoldPHIArgBinOpIntoPHI(PHINode &PN) {
NewLHS, NewRHS);
}
+/// isSafeToSinkLoad - Return true if we know that it is safe sink the load out
+/// of the block that defines it. This means that it must be obvious the value
+/// of the load is not changed from the point of the load to the end of the
+/// block it is in.
+static bool isSafeToSinkLoad(LoadInst *L) {
+ BasicBlock::iterator BBI = L, E = L->getParent()->end();
+
+ for (++BBI; BBI != E; ++BBI)
+ if (BBI->mayWriteToMemory())
+ return false;
+ return true;
+}
+
// FoldPHIArgOpIntoPHI - If all operands to a PHI node are the same "unary"
// operator and they all are only used by the PHI, PHI together their
@@ -6846,6 +6859,7 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
// code size and simplifying code.
Constant *ConstantOp = 0;
const Type *CastSrcTy = 0;
+ bool isVolatile = false;
if (isa<CastInst>(FirstInst)) {
CastSrcTy = FirstInst->getOperand(0)->getType();
} else if (isa<BinaryOperator>(FirstInst) || isa<ShiftInst>(FirstInst)) {
@@ -6854,6 +6868,13 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
ConstantOp = dyn_cast<Constant>(FirstInst->getOperand(1));
if (ConstantOp == 0)
return FoldPHIArgBinOpIntoPHI(PN);
+ } else if (LoadInst *LI = dyn_cast<LoadInst>(FirstInst)) {
+ isVolatile = LI->isVolatile();
+ // We can't sink the load if the loaded value could be modified between the
+ // load and the PHI.
+ if (LI->getParent() != PN.getIncomingBlock(0) ||
+ !isSafeToSinkLoad(LI))
+ return 0;
} else {
return 0; // Cannot fold this operation.
}
@@ -6867,6 +6888,13 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
if (CastSrcTy) {
if (I->getOperand(0)->getType() != CastSrcTy)
return 0; // Cast operation must match.
+ } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
+ // We can't sink the load if the loaded value could be modified between the
+ // load and the PHI.
+ if (LI->isVolatile() != isVolatile ||
+ LI->getParent() != PN.getIncomingBlock(i) ||
+ !isSafeToSinkLoad(LI))
+ return 0;
} else if (I->getOperand(1) != ConstantOp) {
return 0;
}
@@ -6903,6 +6931,8 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) {
// Insert and return the new operation.
if (isa<CastInst>(FirstInst))
return new CastInst(PhiVal, PN.getType());
+ else if (LoadInst *LI = dyn_cast<LoadInst>(FirstInst))
+ return new LoadInst(PhiVal, "", isVolatile);
else if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(FirstInst))
return BinaryOperator::create(BinOp->getOpcode(), PhiVal, ConstantOp);
else
@@ -7537,47 +7567,6 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) {
LI.setOperand(0, SI->getOperand(1));
return &LI;
}
-
- } else if (PHINode *PN = dyn_cast<PHINode>(Op)) {
- // load (phi (&V1, &V2, &V3)) --> phi(load &V1, load &V2, load &V3)
- bool Safe = PN->getParent() == LI.getParent();
-
- // Scan all of the instructions between the PHI and the load to make
- // sure there are no instructions that might possibly alter the value
- // loaded from the PHI.
- if (Safe) {
- BasicBlock::iterator I = &LI;
- for (--I; !isa<PHINode>(I); --I)
- if (isa<StoreInst>(I) || isa<CallInst>(I)) {
- Safe = false;
- break;
- }
- }
-
- for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e && Safe; ++i)
- if (!isSafeToLoadUnconditionally(PN->getIncomingValue(i),
- PN->getIncomingBlock(i)->getTerminator()))
- Safe = false;
-
- if (Safe) {
- // Create the PHI.
- PHINode *NewPN = new PHINode(LI.getType(), PN->getName());
- InsertNewInstBefore(NewPN, *PN);
- std::map<BasicBlock*,Value*> LoadMap; // Don't insert duplicate loads
-
- for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
- BasicBlock *BB = PN->getIncomingBlock(i);
- Value *&TheLoad = LoadMap[BB];
- if (TheLoad == 0) {
- Value *InVal = PN->getIncomingValue(i);
- TheLoad = InsertNewInstBefore(new LoadInst(InVal,
- InVal->getName()+".val"),
- *BB->getTerminator());
- }
- NewPN->addIncoming(TheLoad, BB);
- }
- return ReplaceInstUsesWith(LI, NewPN);
- }
}
}
return 0;