diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index cc8c5a12324..f21bd8485a4 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -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(I) || isa(I) || isa(I)) { + if (isa(I) || isa(I) || isa(I) || + isa(I)) { PrintAllTypes = true; } else { for (unsigned i = 1, E = I.getNumOperands(); i != E; ++i) { diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 94c8651609d..f12a041df04 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -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) { diff --git a/lib/VMCore/ConstantFold.h b/lib/VMCore/ConstantFold.h index 7914a1cbfda..5119aaf3f7e 100644 --- a/lib/VMCore/ConstantFold.h +++ b/lib/VMCore/ConstantFold.h @@ -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, diff --git a/lib/VMCore/ConstantFolding.h b/lib/VMCore/ConstantFolding.h index 7914a1cbfda..5119aaf3f7e 100644 --- a/lib/VMCore/ConstantFolding.h +++ b/lib/VMCore/ConstantFolding.h @@ -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, diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 55bc4aef04c..9f706b9bc1b 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -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 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 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() { diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index a44b5e4b11a..fe4ba507c17 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -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 " "; } diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index f28a413a172..9ef72d43536 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -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(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(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(V1->getType())) return false; + if (V1->getType() != V2->getType()) return false; + if (!isa(Mask->getType()) || + cast(Mask->getType())->getElementType() != Type::UIntTy || + cast(Mask->getType())->getNumElements() != + cast(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); } diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index d672901cc17..b7396695c41 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -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(SV.getOperand(2))) { + for (unsigned i = 0, e = MV->getNumOperands(); i != e; ++i) { + Assert1(isa(MV->getOperand(i)) || + isa(MV->getOperand(i)), + "Invalid shufflevector shuffle mask!", &SV); + } + } else { + Assert1(isa(SV.getOperand(2)) || + isa(SV.getOperand(2)), + "Invalid shufflevector shuffle mask!", &SV); + } + + visitInstruction(SV); +} + void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { const Type *ElTy = GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(),