// * Assumes values are constant unless proven otherwise
// * Assumes BasicBlocks are dead unless proven otherwise
// * Proves values to be constant, and replaces them with constants
-// * Proves conditional branches constant, and unconditionalizes them
-// * Folds multiple identical constants in the constant pool together
+// * Proves conditional branches to be unconditional
//
// Notice that:
// * This pass has a habit of making definitions be dead. It is a good idea
#include "llvm/Transforms/Scalar.h"
#include "llvm/ConstantHandling.h"
#include "llvm/Function.h"
-#include "llvm/BasicBlock.h"
#include "llvm/iPHINode.h"
#include "llvm/iMemory.h"
#include "llvm/iTerminators.h"
#include "Support/StatisticReporter.h"
#include <algorithm>
#include <set>
-#include <iostream>
using std::cerr;
static Statistic<> NumInstRemoved("sccp\t\t- Number of instructions removed");
enum {
undefined, // This instruction has no known value
constant, // This instruction has a constant value
- // Range, // This instruction is known to fall within a range
overdefined // This instruction has an unknown value
} LatticeValue; // The current lattice position
Constant *ConstantVal; // If Constant value, the current value
ValueState[CPV].markConstant(CPV);
} else if (isa<Argument>(V)) { // Arguments are overdefined
ValueState[V].markOverdefined();
- }
+ } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
+ // The address of a global is a constant...
+ ValueState[V].markConstant(ConstantPointerRef::get(GV));
+ }
// All others are underdefined by default...
return ValueState[V];
}
void visitReturnInst(ReturnInst &I) { /*does not have an effect*/ }
void visitTerminatorInst(TerminatorInst &TI);
- void visitUnaryOperator(Instruction &I);
- void visitCastInst(CastInst &I) { visitUnaryOperator(I); }
+ void visitCastInst(CastInst &I);
void visitBinaryOperator(Instruction &I);
void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); }
// Instructions that cannot be folded away...
void visitStoreInst (Instruction &I) { /*returns void*/ }
- void visitMemAccessInst (Instruction &I) { markOverdefined(&I); }
+ void visitLoadInst (Instruction &I) { markOverdefined(&I); }
+ void visitGetElementPtrInst(GetElementPtrInst &I);
void visitCallInst (Instruction &I) { markOverdefined(&I); }
void visitInvokeInst (Instruction &I) { markOverdefined(&I); }
void visitAllocationInst(Instruction &I) { markOverdefined(&I); }
}
}
-void SCCP::visitUnaryOperator(Instruction &I) {
+void SCCP::visitCastInst(CastInst &I) {
Value *V = I.getOperand(0);
InstVal &VState = getValueState(V);
if (VState.isOverdefined()) { // Inherit overdefinedness of operand
markOverdefined(&I);
} else if (VState.isConstant()) { // Propogate constant value
- Constant *Result = isa<CastInst>(I)
- ? ConstantFoldCastInstruction(VState.getConstant(), I.getType())
- : ConstantFoldUnaryInstruction(I.getOpcode(), VState.getConstant());
+ Constant *Result =
+ ConstantFoldCastInstruction(VState.getConstant(), I.getType());
if (Result) {
// This instruction constant folds!
markOverdefined(&I); // Don't know how to fold this instruction. :(
}
}
+
+// Handle getelementptr instructions... if all operands are constants then we
+// can turn this into a getelementptr ConstantExpr.
+//
+void SCCP::visitGetElementPtrInst(GetElementPtrInst &I) {
+ std::vector<Constant*> Operands;
+ Operands.reserve(I.getNumOperands());
+
+ for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
+ InstVal &State = getValueState(I.getOperand(i));
+ if (State.isUndefined())
+ return; // Operands are not resolved yet...
+ else if (State.isOverdefined()) {
+ markOverdefined(&I);
+ return;
+ }
+ assert(State.isConstant() && "Unknown state!");
+ Operands.push_back(State.getConstant());
+ }
+
+ Constant *Ptr = Operands[0];
+ Operands.erase(Operands.begin()); // Erase the pointer from idx list...
+
+ markConstant(&I, ConstantExpr::getGetElementPtr(Ptr, Operands));
+}