aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Scalar/InstructionCombining.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/Scalar/InstructionCombining.cpp')
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp18
1 files changed, 18 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp
index 32686b3e85..a874723b54 100644
--- a/lib/Transforms/Scalar/InstructionCombining.cpp
+++ b/lib/Transforms/Scalar/InstructionCombining.cpp
@@ -4018,6 +4018,24 @@ bool InstCombiner::runOnFunction(Function &F) {
// Instruction isn't dead, see if we can constant propagate it...
if (Constant *C = ConstantFoldInstruction(I)) {
+ if (isa<GetElementPtrInst>(I) &&
+ cast<Constant>(I->getOperand(0))->isNullValue() &&
+ !isa<ConstantPointerNull>(C)) {
+ // If this is a constant expr gep that is effectively computing an
+ // "offsetof", fold it into 'cast int X to T*' instead of 'gep 0, 0, 12'
+ bool isFoldableGEP = true;
+ for (unsigned i = 1, e = I->getNumOperands(); i != e; ++i)
+ if (!isa<ConstantInt>(I->getOperand(i)))
+ isFoldableGEP = false;
+ if (isFoldableGEP) {
+ uint64_t Offset = TD->getIndexedOffset(I->getOperand(0)->getType(),
+ std::vector<Value*>(I->op_begin()+1, I->op_end()));
+ C = ConstantUInt::get(Type::ULongTy, Offset);
+ C = ConstantUInt::getCast(C, TD->getIntPtrType());
+ C = ConstantExpr::getCast(C, I->getType());
+ }
+ }
+
// Add operands to the worklist...
AddUsesToWorkList(*I);
ReplaceInstUsesWith(*I, C);