diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index b942010f10c..05018fa1617 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -61,6 +61,12 @@ Constant *ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, const TargetData *TD = 0); +/// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue +/// instruction with the specified operands and indices. The constant result is +/// returned if successful; if not, null is returned. +Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, + ArrayRef Idxs); + /// ConstantFoldLoadFromConstPtr - Return the value that a load from C would /// produce if it is constant and determinable. If this is not determinable, /// return null. diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 94bdae21b5d..c1d87d3f771 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -126,6 +126,13 @@ namespace llvm { Value *SimplifyGEPInst(ArrayRef Ops, const TargetData *TD = 0, const DominatorTree *DT = 0); + /// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we + /// can fold the result. If not, this returns null. + Value *SimplifyInsertValueInst(Value *Agg, Value *Val, + ArrayRef Idxs, + const TargetData *TD = 0, + const DominatorTree *DT = 0); + //=== Helper functions for higher up the class hierarchy. diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index cfff9c03c83..deb7fed18b3 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -2270,6 +2270,35 @@ Value *llvm::SimplifyGEPInst(ArrayRef Ops, return ConstantExpr::getGetElementPtr(cast(Ops[0]), Ops.slice(1)); } +/// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we +/// can fold the result. If not, this returns null. +Value *llvm::SimplifyInsertValueInst(Value *Agg, Value *Val, + ArrayRef Idxs, + const TargetData *, + const DominatorTree *) { + if (Constant *CAgg = dyn_cast(Agg)) + if (Constant *CVal = dyn_cast(Val)) + return ConstantFoldInsertValueInstruction(CAgg, CVal, Idxs); + + // insertvalue x, undef, n -> x + if (match(Val, m_Undef())) + return Agg; + + // insertvalue x, (extractvalue y, n), n + if (ExtractValueInst *EV = dyn_cast(Val)) + if (EV->getIndices() == Idxs) { + // insertvalue undef, (extractvalue y, n), n -> y + if (match(Agg, m_Undef())) + return EV->getAggregateOperand(); + + // insertvalue y, (extractvalue y, n), n -> y + if (Agg == EV->getAggregateOperand()) + return Agg; + } + + return 0; +} + /// SimplifyPHINode - See if we can fold the given phi. If not, returns null. static Value *SimplifyPHINode(PHINode *PN, const DominatorTree *DT) { // If all of the PHI's incoming values are the same then replace the PHI node @@ -2471,6 +2500,13 @@ Value *llvm::SimplifyInstruction(Instruction *I, const TargetData *TD, Result = SimplifyGEPInst(Ops, TD, DT); break; } + case Instruction::InsertValue: { + InsertValueInst *IV = cast(I); + Result = SimplifyInsertValueInst(IV->getAggregateOperand(), + IV->getInsertedValueOperand(), + IV->getIndices(), TD, DT); + break; + } case Instruction::PHI: Result = SimplifyPHINode(cast(I), DT); break; diff --git a/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll b/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll new file mode 100644 index 00000000000..4067d5dc76c --- /dev/null +++ b/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -instsimplify -S | FileCheck %s + +; CHECK-NOT: extractvalue +; CHECK-NOT: insertvalue + +declare void @bar() + +define void @foo() { +entry: + invoke void @bar() to label %cont unwind label %lpad +cont: + ret void +lpad: + %ex = landingpad { i8*, i32 } personality i32 (i32, i64, i8*, i8*)* @__gxx_personality_v0 cleanup + %exc_ptr = extractvalue { i8*, i32 } %ex, 0 + %filter = extractvalue { i8*, i32 } %ex, 1 + %exc_ptr2 = insertvalue { i8*, i32 } undef, i8* %exc_ptr, 0 + %filter2 = insertvalue { i8*, i32 } %exc_ptr2, i32 %filter, 1 + resume { i8*, i32 } %filter2 +} + +declare i32 @__gxx_personality_v0(i32, i64, i8*, i8*)