extract element from a shuffle vector can be trivially turned into an
authorChris Lattner <sabre@nondot.org>
Thu, 25 May 2006 22:53:38 +0000 (22:53 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 25 May 2006 22:53:38 +0000 (22:53 +0000)
extractelement from the SV's source.  This implement vec_shuffle.ll:test[45]

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28485 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/InstructionCombining.cpp

index 2a48fc06c94bc9fc4866fd7169596459fcd514fe..8bb23226e487e55971aba26ca7cfac347a3bb04f 100644 (file)
@@ -7072,7 +7072,7 @@ Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) {
       return ReplaceInstUsesWith(EI, Elt);
   }
   
-  if (Instruction *I = dyn_cast<Instruction>(EI.getOperand(0)))
+  if (Instruction *I = dyn_cast<Instruction>(EI.getOperand(0))) {
     if (I->hasOneUse()) {
       // Push extractelement into predecessor operation if legal and
       // profitable to do so
@@ -7097,20 +7097,49 @@ Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) {
                                 I->getName() + ".gep");
         InsertNewInstBefore(GEP, EI);
         return new LoadInst(GEP);
-      } else if (InsertElementInst *IE = dyn_cast<InsertElementInst>(I)) {
-        // Extracting the inserted element?
-        if (IE->getOperand(2) == EI.getOperand(1))
-          return ReplaceInstUsesWith(EI, IE->getOperand(1));
-        // If the inserted and extracted elements are constants, they must not
-        // be the same value, extract from the pre-inserted value instead.
-        if (isa<Constant>(IE->getOperand(2)) &&
-            isa<Constant>(EI.getOperand(1))) {
-          AddUsesToWorkList(EI);
-          EI.setOperand(0, IE->getOperand(0));
-          return &EI;
+      }
+    }
+    if (InsertElementInst *IE = dyn_cast<InsertElementInst>(I)) {
+      // Extracting the inserted element?
+      if (IE->getOperand(2) == EI.getOperand(1))
+        return ReplaceInstUsesWith(EI, IE->getOperand(1));
+      // If the inserted and extracted elements are constants, they must not
+      // be the same value, extract from the pre-inserted value instead.
+      if (isa<Constant>(IE->getOperand(2)) &&
+          isa<Constant>(EI.getOperand(1))) {
+        AddUsesToWorkList(EI);
+        EI.setOperand(0, IE->getOperand(0));
+        return &EI;
+      }
+    } else if (ShuffleVectorInst *SVI = dyn_cast<ShuffleVectorInst>(I)) {
+      // If this is extracting an element from a shufflevector, figure out where
+      // it came from and extract from the appropriate input element instead.
+      if (ConstantUInt *Elt = dyn_cast<ConstantUInt>(EI.getOperand(1))) {
+        unsigned ExtractedIdx = Elt->getValue();
+        if (ConstantPacked *CP = dyn_cast<ConstantPacked>(SVI->getOperand(2))) {
+          unsigned Idx = 0;
+          if (ConstantUInt *CI = 
+              dyn_cast<ConstantUInt>(CP->getOperand(ExtractedIdx)))
+            Idx = CI->getValue();
+          Value *Src;
+          if (Idx < CP->getNumOperands())
+            Src = SVI->getOperand(0);
+          else {
+            Idx -= CP->getNumOperands();
+            Src = SVI->getOperand(0);
+          }
+          return new ExtractElementInst(Src,
+                                        ConstantUInt::get(Type::UIntTy, Idx));
+     
+        } else if (isa<ConstantAggregateZero>(SVI->getOperand(2))) {
+          // If extracting from a splat of the 0th element, return an extract
+          // of the zero'th element of the input to the splat.
+          return new ExtractElementInst(SVI->getOperand(0),
+                                        ConstantUInt::get(Type::UIntTy, 0));
         }
       }
     }
+  }
   return 0;
 }