From 5501985a583038523e787cc60218717b32631c88 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Mon, 13 Jul 2015 01:15:46 +0000 Subject: [PATCH] [InstSimplify] Teach InstSimplify how to simplify extractvalue git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242007 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/ConstantFolding.h | 6 +++ include/llvm/Analysis/InstructionSimplify.h | 9 ++++ lib/Analysis/InstructionSimplify.cpp | 41 +++++++++++++++++++ .../InstCombine/InstructionCombining.cpp | 13 ++---- .../2011-09-05-InsertExtractValue.ll | 9 ++++ 5 files changed, 68 insertions(+), 10 deletions(-) diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index 541a2109af6..e67e2651c89 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -72,6 +72,12 @@ namespace llvm { Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, ArrayRef Idxs); +/// \brief Attempt to constant fold an extractvalue instruction with the +/// specified operands and indices. The constant result is returned if +/// successful; if not, null is returned. +Constant *ConstantFoldExtractValueInstruction(Constant *Agg, + 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 65654b1ba34..0ed379062bb 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -244,6 +244,15 @@ namespace llvm { AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); + /// \brief Given operands for an ExtractValueInst, see if we can fold the + /// result. If not, this returns null. + Value *SimplifyExtractValueInst(Value *Agg, ArrayRef Idxs, + const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); + /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold /// the result. If not, this returns null. Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL, diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index ab5cd01ab63..ad85a3ed73c 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -3520,6 +3520,41 @@ Value *llvm::SimplifyInsertValueInst( RecursionLimit); } +/// SimplifyExtractValueInst - Given operands for an ExtractValueInst, see if we +/// can fold the result. If not, this returns null. +static Value *SimplifyExtractValueInst(Value *Agg, ArrayRef Idxs, + const Query &, unsigned) { + if (auto *CAgg = dyn_cast(Agg)) + return ConstantFoldExtractValueInstruction(CAgg, Idxs); + + // extractvalue x, (insertvalue y, elt, n), n -> elt + unsigned NumIdxs = Idxs.size(); + for (auto *IVI = dyn_cast(Agg); IVI != nullptr; + IVI = dyn_cast(IVI->getAggregateOperand())) { + ArrayRef InsertValueIdxs = IVI->getIndices(); + unsigned NumInsertValueIdxs = InsertValueIdxs.size(); + unsigned NumCommonIdxs = std::min(NumInsertValueIdxs, NumIdxs); + if (InsertValueIdxs.slice(0, NumCommonIdxs) == + Idxs.slice(0, NumCommonIdxs)) { + if (NumIdxs == NumInsertValueIdxs) + return IVI->getInsertedValueOperand(); + break; + } + } + + return nullptr; +} + +Value *llvm::SimplifyExtractValueInst(Value *Agg, ArrayRef Idxs, + const DataLayout &DL, + const TargetLibraryInfo *TLI, + const DominatorTree *DT, + AssumptionCache *AC, + const Instruction *CxtI) { + return ::SimplifyExtractValueInst(Agg, Idxs, Query(DL, TLI, DT, AC, CxtI), + RecursionLimit); +} + /// SimplifyPHINode - See if we can fold the given phi. If not, returns null. static Value *SimplifyPHINode(PHINode *PN, const Query &Q) { // If all of the PHI's incoming values are the same then replace the PHI node @@ -3929,6 +3964,12 @@ Value *llvm::SimplifyInstruction(Instruction *I, const DataLayout &DL, IV->getIndices(), DL, TLI, DT, AC, I); break; } + case Instruction::ExtractValue: { + auto *EVI = cast(I); + Result = SimplifyExtractValueInst(EVI->getAggregateOperand(), + EVI->getIndices(), DL, TLI, DT, AC, I); + break; + } case Instruction::PHI: Result = SimplifyPHINode(cast(I), Query(DL, TLI, DT, AC, I)); break; diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index ea4089b1573..fd34a244f27 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2174,16 +2174,9 @@ Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) { if (!EV.hasIndices()) return ReplaceInstUsesWith(EV, Agg); - if (Constant *C = dyn_cast(Agg)) { - if (Constant *C2 = C->getAggregateElement(*EV.idx_begin())) { - if (EV.getNumIndices() == 0) - return ReplaceInstUsesWith(EV, C2); - // Extract the remaining indices out of the constant indexed by the - // first index - return ExtractValueInst::Create(C2, EV.getIndices().slice(1)); - } - return nullptr; // Can't handle other constants - } + if (Value *V = + SimplifyExtractValueInst(Agg, EV.getIndices(), DL, TLI, DT, AC)) + return ReplaceInstUsesWith(EV, V); if (InsertValueInst *IV = dyn_cast(Agg)) { // We're extracting from an insertvalue instruction, compare the indices diff --git a/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll b/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll index 885cb70007e..7e391aba304 100644 --- a/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll +++ b/test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll @@ -27,3 +27,12 @@ define { i8, i32 } @test2({ i8*, i32 } %x) { ret { i8, i32 } %ins ; CHECK-LABEL: @test2( } + +define i32 @test3(i32 %a, float %b) { + %agg1 = insertvalue {i32, float} undef, i32 %a, 0 + %agg2 = insertvalue {i32, float} %agg1, float %b, 1 + %ev = extractvalue {i32, float} %agg2, 0 + ret i32 %ev +; CHECK-LABEL: @test3( +; CHECK: ret i32 %a +}