[InstSimplify] Teach InstSimplify how to simplify extractvalue
authorDavid Majnemer <david.majnemer@gmail.com>
Mon, 13 Jul 2015 01:15:46 +0000 (01:15 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Mon, 13 Jul 2015 01:15:46 +0000 (01:15 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@242007 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Analysis/ConstantFolding.h
include/llvm/Analysis/InstructionSimplify.h
lib/Analysis/InstructionSimplify.cpp
lib/Transforms/InstCombine/InstructionCombining.cpp
test/Transforms/InstSimplify/2011-09-05-InsertExtractValue.ll

index 541a2109af6cde4a5ddd83422e34c51a29fd49b0..e67e2651c893f261cd2bbf90ab68b187acc2ab80 100644 (file)
@@ -72,6 +72,12 @@ namespace llvm {
 Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
                                              ArrayRef<unsigned> 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<unsigned> 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.
index 65654b1ba34271e6a9f0b4438b2deeaab435d120..0ed379062bb1f62b4793332b3625028502b5f601 100644 (file)
@@ -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<unsigned> 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,
index ab5cd01ab634744a976aa8f0b7d69050703e04f5..ad85a3ed73cb67f20b8fad450a7ea3942988c21f 100644 (file)
@@ -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<unsigned> Idxs,
+                                       const Query &, unsigned) {
+  if (auto *CAgg = dyn_cast<Constant>(Agg))
+    return ConstantFoldExtractValueInstruction(CAgg, Idxs);
+
+  // extractvalue x, (insertvalue y, elt, n), n -> elt
+  unsigned NumIdxs = Idxs.size();
+  for (auto *IVI = dyn_cast<InsertValueInst>(Agg); IVI != nullptr;
+       IVI = dyn_cast<InsertValueInst>(IVI->getAggregateOperand())) {
+    ArrayRef<unsigned> 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<unsigned> 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<ExtractValueInst>(I);
+    Result = SimplifyExtractValueInst(EVI->getAggregateOperand(),
+                                      EVI->getIndices(), DL, TLI, DT, AC, I);
+    break;
+  }
   case Instruction::PHI:
     Result = SimplifyPHINode(cast<PHINode>(I), Query(DL, TLI, DT, AC, I));
     break;
index ea4089b15733475b490954dc6e39fb37e54d7772..fd34a244f271af8c578488e6f9ea4af185d0ce58 100644 (file)
@@ -2174,16 +2174,9 @@ Instruction *InstCombiner::visitExtractValueInst(ExtractValueInst &EV) {
   if (!EV.hasIndices())
     return ReplaceInstUsesWith(EV, Agg);
 
-  if (Constant *C = dyn_cast<Constant>(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<InsertValueInst>(Agg)) {
     // We're extracting from an insertvalue instruction, compare the indices
index 885cb70007e673ff7552e1bcae7bd619b5cecb42..7e391aba30456b2204a85252b9f0cff0a028214c 100644 (file)
@@ -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
+}