summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-01-12 04:29:41 +0000
committerChris Lattner <sabre@nondot.org>2004-01-12 04:29:41 +0000
commit49f74522ec524512c1a40c76fe324cc93d988666 (patch)
tree912419b47ea89d64c2da34615a7237a245021cbf /llvm/lib/Transforms
parent2ca9b10b6ae68c447a5eb67dfa1fe0f012238003 (diff)
downloadbcm5719-llvm-49f74522ec524512c1a40c76fe324cc93d988666.tar.gz
bcm5719-llvm-49f74522ec524512c1a40c76fe324cc93d988666.zip
* Implement minor performance optimization for the getelementptr case
* Implement SCCP of load instructions, implementing Transforms/SCCP/loadtest.ll This allows us to fold expressions like "foo"[2], even if the pointer is only a conditional constant. llvm-svn: 10767
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Scalar/SCCP.cpp72
1 files changed, 69 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp
index 2d8171dd8dd..3c92afe8cf5 100644
--- a/llvm/lib/Transforms/Scalar/SCCP.cpp
+++ b/llvm/lib/Transforms/Scalar/SCCP.cpp
@@ -24,6 +24,7 @@
#include "llvm/Transforms/Scalar.h"
#include "llvm/ConstantHandling.h"
#include "llvm/Function.h"
+#include "llvm/GlobalVariable.h"
#include "llvm/Instructions.h"
#include "llvm/Pass.h"
#include "llvm/Support/InstVisitor.h"
@@ -215,7 +216,7 @@ private:
// Instructions that cannot be folded away...
void visitStoreInst (Instruction &I) { /*returns void*/ }
- void visitLoadInst (Instruction &I) { markOverdefined(&I); }
+ void visitLoadInst (LoadInst &I);
void visitGetElementPtrInst(GetElementPtrInst &I);
void visitCallInst (Instruction &I) { markOverdefined(&I); }
void visitInvokeInst (TerminatorInst &I) {
@@ -666,6 +667,9 @@ void SCCP::visitBinaryOperator(Instruction &I) {
// can turn this into a getelementptr ConstantExpr.
//
void SCCP::visitGetElementPtrInst(GetElementPtrInst &I) {
+ InstVal &IV = ValueState[&I];
+ if (IV.isOverdefined()) return;
+
std::vector<Constant*> Operands;
Operands.reserve(I.getNumOperands());
@@ -674,7 +678,7 @@ void SCCP::visitGetElementPtrInst(GetElementPtrInst &I) {
if (State.isUndefined())
return; // Operands are not resolved yet...
else if (State.isOverdefined()) {
- markOverdefined(&I);
+ markOverdefined(IV, &I);
return;
}
assert(State.isConstant() && "Unknown state!");
@@ -684,6 +688,68 @@ void SCCP::visitGetElementPtrInst(GetElementPtrInst &I) {
Constant *Ptr = Operands[0];
Operands.erase(Operands.begin()); // Erase the pointer from idx list...
- markConstant(&I, ConstantExpr::getGetElementPtr(Ptr, Operands));
+ markConstant(IV, &I, ConstantExpr::getGetElementPtr(Ptr, Operands));
+}
+
+/// GetGEPGlobalInitializer - Given a constant and a getelementptr constantexpr,
+/// return the constant value being addressed by the constant expression, or
+/// null if something is funny.
+///
+static Constant *GetGEPGlobalInitializer(Constant *C, ConstantExpr *CE) {
+ if (CE->getOperand(1) != Constant::getNullValue(Type::LongTy))
+ return 0; // Do not allow stepping over the value!
+
+ // Loop over all of the operands, tracking down which value we are
+ // addressing...
+ for (unsigned i = 2, e = CE->getNumOperands(); i != e; ++i)
+ if (ConstantUInt *CU = dyn_cast<ConstantUInt>(CE->getOperand(i))) {
+ ConstantStruct *CS = cast<ConstantStruct>(C);
+ if (CU->getValue() >= CS->getValues().size()) return 0;
+ C = cast<Constant>(CS->getValues()[CU->getValue()]);
+ } else if (ConstantSInt *CS = dyn_cast<ConstantSInt>(CE->getOperand(i))) {
+ ConstantArray *CA = cast<ConstantArray>(C);
+ if ((uint64_t)CS->getValue() >= CA->getValues().size()) return 0;
+ C = cast<Constant>(CA->getValues()[CS->getValue()]);
+ } else
+ return 0;
+ return C;
}
+// Handle load instructions. If the operand is a constant pointer to a constant
+// global, we can replace the load with the loaded constant value!
+void SCCP::visitLoadInst(LoadInst &I) {
+ InstVal &IV = ValueState[&I];
+ if (IV.isOverdefined()) return;
+
+ InstVal &PtrVal = getValueState(I.getOperand(0));
+ if (PtrVal.isUndefined()) return; // The pointer is not resolved yet!
+ if (PtrVal.isConstant() && !I.isVolatile()) {
+ Value *Ptr = PtrVal.getConstant();
+ if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(Ptr))
+ Ptr = CPR->getValue();
+
+ // Transform load (constant global) into the value loaded.
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr))
+ if (GV->isConstant() && !GV->isExternal()) {
+ markConstant(IV, &I, GV->getInitializer());
+ return;
+ }
+
+ // Transform load (constantexpr_GEP global, 0, ...) into the value loaded.
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr))
+ if (CE->getOpcode() == Instruction::GetElementPtr)
+ if (ConstantPointerRef *G
+ = dyn_cast<ConstantPointerRef>(CE->getOperand(0)))
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(G->getValue()))
+ if (GV->isConstant() && !GV->isExternal())
+ if (Constant *V =
+ GetGEPGlobalInitializer(GV->getInitializer(), CE)) {
+ markConstant(IV, &I, V);
+ return;
+ }
+ }
+
+ // Otherwise we cannot say for certain what value this load will produce.
+ // Bail out.
+ markOverdefined(IV, &I);
+}
OpenPOWER on IntegriCloud