Add shufflevector support, todo, implement better constant folding.
authorChris Lattner <sabre@nondot.org>
Sat, 8 Apr 2006 01:18:18 +0000 (01:18 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 8 Apr 2006 01:18:18 +0000 (01:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27510 91177308-0d34-0410-b5e6-96231b3b80d8

lib/VMCore/AsmWriter.cpp
lib/VMCore/ConstantFold.cpp
lib/VMCore/ConstantFold.h
lib/VMCore/ConstantFolding.h
lib/VMCore/Constants.cpp
lib/VMCore/Instruction.cpp
lib/VMCore/Instructions.cpp
lib/VMCore/Verifier.cpp

index cc8c5a12324fa78dc28f4b6182dad9ef83c3b160..f21bd8485a4c00f57c93d3286d60f8899561bbe1 100644 (file)
@@ -1237,7 +1237,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
 
     // Shift Left & Right print both types even for Ubyte LHS, and select prints
     // types even if all operands are bools.
-    if (isa<ShiftInst>(I) || isa<SelectInst>(I) || isa<StoreInst>(I)) {
+    if (isa<ShiftInst>(I) || isa<SelectInst>(I) || isa<StoreInst>(I) ||
+        isa<ShuffleVectorInst>(I)) {
       PrintAllTypes = true;
     } else {
       for (unsigned i = 1, E = I.getNumOperands(); i != E; ++i) {
index 94c8651609d8bba3001e00536dc6cacaba30abc4..f12a041df0492a86ce7a64971c6932f119df23a8 100644 (file)
@@ -908,6 +908,14 @@ Constant *llvm::ConstantFoldInsertElementInstruction(const Constant *Val,
   return 0;
 }
 
+Constant *llvm::ConstantFoldShuffleVectorInstruction(const Constant *V1,
+                                                     const Constant *V2,
+                                                     const Constant *Mask) {
+  // TODO:
+  return 0;
+}
+
+
 /// isZeroSizedType - This type is zero sized if its an array or structure of
 /// zero sized types.  The only leaf zero sized type is an empty structure.
 static bool isMaybeZeroSizedType(const Type *Ty) {
index 7914a1cbfdae05e60d8a5d8d9812dba63225bfce..5119aaf3f7eea04a5c4c98b648a1734d09cd78e4 100644 (file)
@@ -36,6 +36,9 @@ namespace llvm {
   Constant *ConstantFoldInsertElementInstruction(const Constant *Val,
                                                  const Constant *Elt,
                                                  const Constant *Idx);
+  Constant *ConstantFoldShuffleVectorInstruction(const Constant *V1,
+                                                 const Constant *V2,
+                                                 const Constant *Mask);
   Constant *ConstantFoldBinaryInstruction(unsigned Opcode, const Constant *V1,
                                           const Constant *V2);
   Constant *ConstantFoldGetElementPtr(const Constant *C,
index 7914a1cbfdae05e60d8a5d8d9812dba63225bfce..5119aaf3f7eea04a5c4c98b648a1734d09cd78e4 100644 (file)
@@ -36,6 +36,9 @@ namespace llvm {
   Constant *ConstantFoldInsertElementInstruction(const Constant *Val,
                                                  const Constant *Elt,
                                                  const Constant *Idx);
+  Constant *ConstantFoldShuffleVectorInstruction(const Constant *V1,
+                                                 const Constant *V2,
+                                                 const Constant *Mask);
   Constant *ConstantFoldBinaryInstruction(unsigned Opcode, const Constant *V1,
                                           const Constant *V2);
   Constant *ConstantFoldGetElementPtr(const Constant *C,
index 55bc4aef04c071a321daf30af15a21c574497afa..9f706b9bc1bd1e102246e477eba713c32ece6067 100644 (file)
@@ -376,6 +376,21 @@ public:
   }
 };
 
+/// ShuffleVectorConstantExpr - This class is private to
+/// Constants.cpp, and is used behind the scenes to implement
+/// shufflevector constant exprs.
+class ShuffleVectorConstantExpr : public ConstantExpr {
+  Use Ops[3];
+public:
+  ShuffleVectorConstantExpr(Constant *C1, Constant *C2, Constant *C3)
+  : ConstantExpr(C1->getType(), Instruction::ShuffleVector, 
+                 Ops, 3) {
+    Ops[0].init(C1, this);
+    Ops[1].init(C2, this);
+    Ops[2].init(C3, this);
+  }
+};
+
 /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
 /// used behind the scenes to implement getelementpr constant exprs.
 struct GetElementPtrConstantExpr : public ConstantExpr {
@@ -1175,7 +1190,10 @@ namespace llvm {
       if (V.first == Instruction::InsertElement)
         return new InsertElementConstantExpr(V.second[0], V.second[1],
                                              V.second[2]);
-
+      if (V.first == Instruction::ShuffleVector)
+        return new ShuffleVectorConstantExpr(V.second[0], V.second[1],
+                                             V.second[2]);
+      
       assert(V.first == Instruction::GetElementPtr && "Invalid ConstantExpr!");
 
       std::vector<Constant*> IdxList(V.second.begin()+1, V.second.end());
@@ -1464,6 +1482,26 @@ Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt,
                             Val, Elt, Idx);
 }
 
+Constant *ConstantExpr::getShuffleVectorTy(const Type *ReqTy, Constant *V1,
+                                           Constant *V2, Constant *Mask) {
+  if (Constant *FC = ConstantFoldShuffleVectorInstruction(V1, V2, Mask))
+    return FC;          // Fold a few common cases...
+  // Look up the constant in the table first to ensure uniqueness
+  std::vector<Constant*> ArgVec(1, V1);
+  ArgVec.push_back(V2);
+  ArgVec.push_back(Mask);
+  const ExprMapKeyType &Key = std::make_pair(Instruction::ShuffleVector,ArgVec);
+  return ExprConstants.getOrCreate(ReqTy, Key);
+}
+
+Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, 
+                                         Constant *Mask) {
+  assert(ShuffleVectorInst::isValidOperands(V1, V2, Mask) &&
+         "Invalid shuffle vector constant expr operands!");
+  return getShuffleVectorTy(V1->getType(), V1, V2, Mask);
+}
+
+
 // destroyConstant - Remove the constant from the constant table...
 //
 void ConstantExpr::destroyConstant() {
index a44b5e4b11ae410e338c5493c6b98fddcd64cacc..fe4ba507c176388a1cbeb030e90f8314150ab529 100644 (file)
@@ -122,6 +122,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
   case VAArg:   return "va_arg";
   case ExtractElement: return "extractelement";
   case InsertElement: return "insertelement";
+  case ShuffleVector: return "shufflevector";
 
   default: return "<Invalid operator> ";
   }
index f28a413a172ace1d94d89dd5ce12d17a7ab71aa1..9ef72d43536d1ee4636140f976c1c8cee02d9e08 100644 (file)
@@ -800,7 +800,8 @@ const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) {
 //===----------------------------------------------------------------------===//
 
 ExtractElementInst::ExtractElementInst(Value *Val, Value *Index,
-                                       const std::string &Name, Instruction *InsertBef)
+                                       const std::string &Name,
+                                       Instruction *InsertBef)
   : Instruction(cast<PackedType>(Val->getType())->getElementType(),
                 ExtractElement, Ops, 2, Name, InsertBef) {
   Ops[0].init(Val, this);
@@ -808,7 +809,8 @@ ExtractElementInst::ExtractElementInst(Value *Val, Value *Index,
 }
 
 ExtractElementInst::ExtractElementInst(Value *Val, Value *Index,
-                                       const std::string &Name, BasicBlock *InsertAE)
+                                       const std::string &Name,
+                                       BasicBlock *InsertAE)
   : Instruction(cast<PackedType>(Val->getType())->getElementType(),
                 ExtractElement, Ops, 2, Name, InsertAE) {
   Ops[0].init(Val, this);
@@ -820,7 +822,8 @@ ExtractElementInst::ExtractElementInst(Value *Val, Value *Index,
 //===----------------------------------------------------------------------===//
 
 InsertElementInst::InsertElementInst(Value *Val, Value *Elt, Value *Index,
-                                     const std::string &Name, Instruction *InsertBef)
+                                     const std::string &Name,
+                                     Instruction *InsertBef)
   : Instruction(Val->getType(), InsertElement, Ops, 3, Name, InsertBef) {
   Ops[0].init(Val, this);
   Ops[1].init(Elt, this);
@@ -828,13 +831,54 @@ InsertElementInst::InsertElementInst(Value *Val, Value *Elt, Value *Index,
 }
 
 InsertElementInst::InsertElementInst(Value *Val, Value *Elt, Value *Index,
-                                     const std::string &Name, BasicBlock *InsertAE)
+                                     const std::string &Name,
+                                     BasicBlock *InsertAE)
   : Instruction(Val->getType(), InsertElement, Ops, 3, Name, InsertAE) {
   Ops[0].init(Val, this);
   Ops[1].init(Elt, this);
   Ops[2].init(Index, this);
 }
 
+//===----------------------------------------------------------------------===//
+//                      ShuffleVectorInst Implementation
+//===----------------------------------------------------------------------===//
+
+ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
+                                     const std::string &Name,
+                                     Instruction *InsertBefore)
+  : Instruction(V1->getType(), ShuffleVector, Ops, 3, Name, InsertBefore) {
+  assert(isValidOperands(V1, V2, Mask) &&
+         "Invalid shuffle vector instruction operands!");
+  Ops[0].init(V1, this);
+  Ops[1].init(V2, this);
+  Ops[2].init(Mask, this);
+}
+
+ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
+                                     const std::string &Name, 
+                                     BasicBlock *InsertAtEnd)
+  : Instruction(V1->getType(), ShuffleVector, Ops, 3, Name, InsertAtEnd) {
+  assert(isValidOperands(V1, V2, Mask) &&
+         "Invalid shuffle vector instruction operands!");
+
+  Ops[0].init(V1, this);
+  Ops[1].init(V2, this);
+  Ops[2].init(Mask, this);
+}
+
+bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2, 
+                                        const Value *Mask) {
+  if (!isa<PackedType>(V1->getType())) return false;
+  if (V1->getType() != V2->getType()) return false;
+  if (!isa<PackedType>(Mask->getType()) ||
+         cast<PackedType>(Mask->getType())->getElementType() != Type::UIntTy ||
+         cast<PackedType>(Mask->getType())->getNumElements() !=
+         cast<PackedType>(V1->getType())->getNumElements())
+    return false;
+  return true;
+}
+
+
 //===----------------------------------------------------------------------===//
 //                             BinaryOperator Class
 //===----------------------------------------------------------------------===//
@@ -1202,8 +1246,15 @@ CallInst   *CallInst::clone()   const { return new CallInst(*this); }
 ShiftInst  *ShiftInst::clone()  const { return new ShiftInst(*this); }
 SelectInst *SelectInst::clone() const { return new SelectInst(*this); }
 VAArgInst  *VAArgInst::clone()  const { return new VAArgInst(*this); }
-ExtractElementInst *ExtractElementInst::clone() const {return new ExtractElementInst(*this); }
-InsertElementInst *InsertElementInst::clone() const {return new InsertElementInst(*this); }
+ExtractElementInst *ExtractElementInst::clone() const {
+  return new ExtractElementInst(*this);
+}
+InsertElementInst *InsertElementInst::clone() const {
+  return new InsertElementInst(*this);
+}
+ShuffleVectorInst *ShuffleVectorInst::clone() const {
+  return new ShuffleVectorInst(*this);
+}
 PHINode    *PHINode::clone()    const { return new PHINode(*this); }
 ReturnInst *ReturnInst::clone() const { return new ReturnInst(*this); }
 BranchInst *BranchInst::clone() const { return new BranchInst(*this); }
index d672901cc17789bf4c011d5b17e449c9c216c06f..b7396695c41b6fec3b27f46bab840e86327d23a1 100644 (file)
@@ -184,6 +184,7 @@ namespace {  // Anonymous namespace for class
     void visitShiftInst(ShiftInst &SI);
     void visitExtractElementInst(ExtractElementInst &EI);
     void visitInsertElementInst(InsertElementInst &EI);
+    void visitShuffleVectorInst(ShuffleVectorInst &EI);
     void visitVAArgInst(VAArgInst &VAA) { visitInstruction(VAA); }
     void visitCallInst(CallInst &CI);
     void visitGetElementPtrInst(GetElementPtrInst &GEP);
@@ -562,6 +563,29 @@ void Verifier::visitInsertElementInst(InsertElementInst &IE) {
   visitInstruction(IE);
 }
 
+void Verifier::visitShuffleVectorInst(ShuffleVectorInst &SV) {
+  Assert1(ShuffleVectorInst::isValidOperands(SV.getOperand(0), SV.getOperand(1),
+                                             SV.getOperand(2)),
+          "Invalid shufflevector operands!", &SV);
+  Assert1(SV.getType() == SV.getOperand(0)->getType(),
+          "Result of shufflevector must match first operand type!", &SV);
+  
+  // Check to see if Mask is valid.
+  if (const ConstantPacked *MV = dyn_cast<ConstantPacked>(SV.getOperand(2))) {
+    for (unsigned i = 0, e = MV->getNumOperands(); i != e; ++i) {
+      Assert1(isa<ConstantUInt>(MV->getOperand(i)) ||
+              isa<UndefValue>(MV->getOperand(i)),
+              "Invalid shufflevector shuffle mask!", &SV);
+    }
+  } else {
+    Assert1(isa<UndefValue>(SV.getOperand(2)) || 
+            isa<ConstantAggregateZero>(SV.getOperand(2)),
+            "Invalid shufflevector shuffle mask!", &SV);
+  }
+  
+  visitInstruction(SV);
+}
+
 void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) {
   const Type *ElTy =
     GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(),