diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 3f7bc7db33a..a6fbf42fa24 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -734,6 +734,63 @@ Constant *llvm::ConstantFoldExtractElementInstruction(const Constant *Val, return 0; } +Constant *llvm::ConstantFoldInsertElementInstruction(const Constant *Val, + const Constant *Elt, + const Constant *Idx) { + const ConstantUInt *CIdx = dyn_cast(Idx); + if (!CIdx) return 0; + unsigned idxVal = CIdx->getValue(); + if (const UndefValue *UVal = dyn_cast(Val)) { + // Insertion of scalar constant into packed undef + // Optimize away insertion of undef + if (isa(Elt)) + return const_cast(Val); + // Otherwise break the aggregate undef into multiple undefs and do + // the insertion + unsigned numOps = + cast(Val->getType())->getNumElements(); + std::vector Ops; + Ops.reserve(numOps); + for (unsigned i = 0; i < numOps; ++i) { + const Constant *Op = + (i == idxVal) ? Elt : UndefValue::get(Elt->getType()); + Ops.push_back(const_cast(Op)); + } + return ConstantPacked::get(Ops); + } + if (const ConstantAggregateZero *CVal = + dyn_cast(Val)) { + // Insertion of scalar constant into packed aggregate zero + // Optimize away insertion of zero + if (Elt->isNullValue()) + return const_cast(Val); + // Otherwise break the aggregate zero into multiple zeros and do + // the insertion + unsigned numOps = + cast(Val->getType())->getNumElements(); + std::vector Ops; + Ops.reserve(numOps); + for (unsigned i = 0; i < numOps; ++i) { + const Constant *Op = + (i == idxVal) ? Elt : Constant::getNullValue(Elt->getType()); + Ops.push_back(const_cast(Op)); + } + return ConstantPacked::get(Ops); + } + if (const ConstantPacked *CVal = dyn_cast(Val)) { + // Insertion of scalar constant into packed constant + std::vector Ops; + Ops.reserve(CVal->getNumOperands()); + for (unsigned i = 0; i < CVal->getNumOperands(); ++i) { + const Constant *Op = + (i == idxVal) ? Elt : cast(CVal->getOperand(i)); + Ops.push_back(const_cast(Op)); + } + return ConstantPacked::get(Ops); + } + 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 e8580c42905..7914a1cbfda 100644 --- a/lib/VMCore/ConstantFold.h +++ b/lib/VMCore/ConstantFold.h @@ -33,6 +33,9 @@ namespace llvm { const Constant *V2); Constant *ConstantFoldExtractElementInstruction(const Constant *Val, const Constant *Idx); + Constant *ConstantFoldInsertElementInstruction(const Constant *Val, + const Constant *Elt, + const Constant *Idx); 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 e8580c42905..7914a1cbfda 100644 --- a/lib/VMCore/ConstantFolding.h +++ b/lib/VMCore/ConstantFolding.h @@ -33,6 +33,9 @@ namespace llvm { const Constant *V2); Constant *ConstantFoldExtractElementInstruction(const Constant *Val, const Constant *Idx); + Constant *ConstantFoldInsertElementInstruction(const Constant *Val, + const Constant *Elt, + const Constant *Idx); 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 f4ff31f24f2..c8a5f356bc0 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -347,8 +347,9 @@ public: } }; -/// ExtractElementConstantExpr - This class is private to Constants.cpp, and is used -/// behind the scenes to implement extractelement constant exprs. +/// ExtractElementConstantExpr - This class is private to +/// Constants.cpp, and is used behind the scenes to implement +/// extractelement constant exprs. class ExtractElementConstantExpr : public ConstantExpr { Use Ops[2]; public: @@ -360,6 +361,21 @@ public: } }; +/// InsertElementConstantExpr - This class is private to +/// Constants.cpp, and is used behind the scenes to implement +/// insertelement constant exprs. +class InsertElementConstantExpr : public ConstantExpr { + Use Ops[3]; +public: + InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3) + : ConstantExpr(C1->getType(), Instruction::InsertElement, + 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 { @@ -1156,6 +1172,9 @@ namespace llvm { return new SelectConstantExpr(V.second[0], V.second[1], V.second[2]); if (V.first == Instruction::ExtractElement) return new ExtractElementConstantExpr(V.second[0], V.second[1]); + if (V.first == Instruction::InsertElement) + return new InsertElementConstantExpr(V.second[0], V.second[1], + V.second[2]); assert(V.first == Instruction::GetElementPtr && "Invalid ConstantExpr!"); @@ -1416,11 +1435,35 @@ Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) { assert(isa(Val->getType()) && "Tried to create extractelement operation on non-packed type!"); assert(Idx->getType() == Type::UIntTy && - "Index must be uint type!"); + "Extractelement index must be uint type!"); return getExtractElementTy(cast(Val->getType())->getElementType(), Val, Idx); } +Constant *ConstantExpr::getInsertElementTy(const Type *ReqTy, Constant *Val, + Constant *Elt, Constant *Idx) { + if (Constant *FC = ConstantFoldInsertElementInstruction(Val, Elt, Idx)) + return FC; // Fold a few common cases... + // Look up the constant in the table first to ensure uniqueness + std::vector ArgVec(1, Val); + ArgVec.push_back(Elt); + ArgVec.push_back(Idx); + const ExprMapKeyType &Key = std::make_pair(Instruction::InsertElement,ArgVec); + return ExprConstants.getOrCreate(ReqTy, Key); +} + +Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt, + Constant *Idx) { + assert(isa(Val->getType()) && + "Tried to create insertelement operation on non-packed type!"); + assert(Elt->getType() == cast(Val->getType())->getElementType() + && "Insertelement types must match!"); + assert(Idx->getType() == Type::UIntTy && + "Insertelement index must be uint type!"); + return getInsertElementTy(cast(Val->getType())->getElementType(), + Val, Elt, Idx); +} + // destroyConstant - Remove the constant from the constant table... // void ConstantExpr::destroyConstant() { diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index 8b13e6e75b7..a44b5e4b11a 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -121,6 +121,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case Shr: return "shr"; case VAArg: return "va_arg"; case ExtractElement: return "extractelement"; + case InsertElement: return "insertelement"; default: return " "; } diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 06fbcf712cd..0bd55c91512 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -800,7 +800,7 @@ 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,13 +808,33 @@ 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); Ops[1].init(Index, this); } +//===----------------------------------------------------------------------===// +// InsertElementInst Implementation +//===----------------------------------------------------------------------===// + +InsertElementInst::InsertElementInst(Value *Val, Value *Elt, Value *Index, + const std::string &Name, Instruction *InsertBef) + : Instruction(Val->getType(), InsertElement, Ops, 3, Name, InsertBef) { + Ops[0].init(Val, this); + Ops[1].init(Elt, this); + Ops[2].init(Index, this); +} + +InsertElementInst::InsertElementInst(Value *Val, Value *Elt, Value *Index, + 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); +} + //===----------------------------------------------------------------------===// // BinaryOperator Class //===----------------------------------------------------------------------===// @@ -1176,6 +1196,7 @@ 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); } 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 ed73341e25e..9f4a6c894d9 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -140,7 +140,7 @@ namespace { // Anonymous namespace for class virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); if (RealPass) - AU.addRequired(); + AU.addRequired(); } /// abortIfBroken - If the module is broken and we are supposed to abort on @@ -180,6 +180,7 @@ namespace { // Anonymous namespace for class void visitBinaryOperator(BinaryOperator &B); void visitShiftInst(ShiftInst &SI); void visitExtractElementInst(ExtractElementInst &EI); + void visitInsertElementInst(InsertElementInst &EI); void visitVAArgInst(VAArgInst &VAA) { visitInstruction(VAA); } void visitCallInst(CallInst &CI); void visitGetElementPtrInst(GetElementPtrInst &GEP); @@ -540,12 +541,24 @@ void Verifier::visitExtractElementInst(ExtractElementInst &EI) { Assert1(EI.getOperand(1)->getType() == Type::UIntTy, "Second operand to extractelement must be uint type!", &EI); Assert1(EI.getType() == - cast(EI.getOperand(0)->getType())->getElementType(), - "Extractelement return type must be same as " - "first operand element type!", &EI); + cast(EI.getOperand(0)->getType())->getElementType(), + "Extractelement return type must match " + "first operand element type!", &EI); visitInstruction(EI); } +void Verifier::visitInsertElementInst(InsertElementInst &IE) { + Assert1(isa(IE.getOperand(0)->getType()), + "First operand to insertelement must be packed type!", &IE); + Assert1(IE.getOperand(1)->getType() == + cast(IE.getOperand(0)->getType())->getElementType(), + "Second operand to insertelement must match " + "first operand element type!", &IE); + Assert1(IE.getOperand(2)->getType() == Type::UIntTy, + "Third operand to insertelement must be uint type!", &IE); + visitInstruction(IE); +} + void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { const Type *ElTy = GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(),