diff options
author | Dan Gohman <gohman@apple.com> | 2008-05-15 19:50:34 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2008-05-15 19:50:34 +0000 |
commit | 8055f7781b0430973392a8ddf54142afb9bcdd3d (patch) | |
tree | bb8e3b74ffb3950147e74e621ffa5e8f14040cd2 /lib/VMCore | |
parent | 7fcd440412730ab1a380d723a418856e4226d9e8 (diff) | |
download | external_llvm-8055f7781b0430973392a8ddf54142afb9bcdd3d.zip external_llvm-8055f7781b0430973392a8ddf54142afb9bcdd3d.tar.gz external_llvm-8055f7781b0430973392a8ddf54142afb9bcdd3d.tar.bz2 |
IR support for extractvalue and insertvalue instructions. Also, begin
moving toward making structs and arrays first-class types.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51157 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/VMCore')
-rw-r--r-- | lib/VMCore/ConstantFold.cpp | 21 | ||||
-rw-r--r-- | lib/VMCore/ConstantFold.h | 4 | ||||
-rw-r--r-- | lib/VMCore/Constants.cpp | 225 | ||||
-rw-r--r-- | lib/VMCore/Instructions.cpp | 69 | ||||
-rw-r--r-- | lib/VMCore/Verifier.cpp | 2 |
5 files changed, 278 insertions, 43 deletions
diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 5138031..0913c48 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -447,6 +447,21 @@ Constant *llvm::ConstantFoldShuffleVectorInstruction(const Constant *V1, return ConstantVector::get(&Result[0], Result.size()); } +Constant *llvm::ConstantFoldExtractValue(const Constant *Agg, + Constant* const *Idxs, + unsigned NumIdx) { + // FIXME: implement some constant folds + return 0; +} + +Constant *llvm::ConstantFoldInsertValue(const Constant *Agg, + const Constant *Val, + Constant* const *Idxs, + unsigned NumIdx) { + // FIXME: implement some constant folds + return 0; +} + /// EvalVectorOp - Given two vector constants and a function pointer, apply the /// function pointer to each element pair, producing a new ConstantVector /// constant. Either or both of V1 and V2 may be NULL, meaning a @@ -1408,8 +1423,7 @@ Constant *llvm::ConstantFoldGetElementPtr(const Constant *C, const PointerType *Ptr = cast<PointerType>(C->getType()); const Type *Ty = GetElementPtrInst::getIndexedType(Ptr, (Value **)Idxs, - (Value **)Idxs+NumIdx, - true); + (Value **)Idxs+NumIdx); assert(Ty != 0 && "Invalid indices for GEP!"); return UndefValue::get(PointerType::get(Ty, Ptr->getAddressSpace())); } @@ -1426,8 +1440,7 @@ Constant *llvm::ConstantFoldGetElementPtr(const Constant *C, const PointerType *Ptr = cast<PointerType>(C->getType()); const Type *Ty = GetElementPtrInst::getIndexedType(Ptr, (Value**)Idxs, - (Value**)Idxs+NumIdx, - true); + (Value**)Idxs+NumIdx); assert(Ty != 0 && "Invalid indices for GEP!"); return ConstantPointerNull::get(PointerType::get(Ty,Ptr->getAddressSpace())); diff --git a/lib/VMCore/ConstantFold.h b/lib/VMCore/ConstantFold.h index 1c1e6e5..bfa6f28 100644 --- a/lib/VMCore/ConstantFold.h +++ b/lib/VMCore/ConstantFold.h @@ -41,6 +41,10 @@ namespace llvm { Constant *ConstantFoldShuffleVectorInstruction(const Constant *V1, const Constant *V2, const Constant *Mask); + Constant *ConstantFoldExtractValue(const Constant *Agg, + Constant* const *Idxs, unsigned NumIdx); + Constant *ConstantFoldInsertValue(const Constant *Agg, const Constant *Val, + Constant* const *Idxs, unsigned NumIdx); Constant *ConstantFoldBinaryInstruction(unsigned Opcode, const Constant *V1, const Constant *V2); Constant *ConstantFoldCompareInstruction(unsigned short predicate, diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 0f7ca0a..75a2b00 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -533,6 +533,43 @@ public: DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); }; +/// ExtractValueConstantExpr - This class is private to +/// Constants.cpp, and is used behind the scenes to implement +/// extractvalue constant exprs. +class VISIBILITY_HIDDEN ExtractValueConstantExpr : public ConstantExpr { + ExtractValueConstantExpr(Constant *Agg, const std::vector<Constant*> &IdxList, + const Type *DestTy); +public: + static ExtractValueConstantExpr *Create(Constant *Agg, + const std::vector<Constant*> &IdxList, + const Type *DestTy) { + return + new(IdxList.size() + 1) ExtractValueConstantExpr(Agg, IdxList, DestTy); + } + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); +}; + +/// InsertValueConstantExpr - This class is private to +/// Constants.cpp, and is used behind the scenes to implement +/// insertvalue constant exprs. +class VISIBILITY_HIDDEN InsertValueConstantExpr : public ConstantExpr { + InsertValueConstantExpr(Constant *Agg, Constant *Val, + const std::vector<Constant*> &IdxList, + const Type *DestTy); +public: + static InsertValueConstantExpr *Create(Constant *Agg, Constant *Val, + const std::vector<Constant*> &IdxList, + const Type *DestTy) { + return + new(IdxList.size() + 2) InsertValueConstantExpr(Agg, Val, + IdxList, DestTy); + } + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); +}; + + /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is /// used behind the scenes to implement getelementpr constant exprs. class VISIBILITY_HIDDEN GetElementPtrConstantExpr : public ConstantExpr { @@ -601,6 +638,45 @@ struct OperandTraits<ShuffleVectorConstantExpr> : FixedNumOperandTraits<3> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value) +template <> +struct OperandTraits<ExtractValueConstantExpr> : VariadicOperandTraits<1> { +}; + +ExtractValueConstantExpr::ExtractValueConstantExpr + (Constant *Agg, + const std::vector<Constant*> &IdxList, + const Type *DestTy) + : ConstantExpr(DestTy, Instruction::ExtractValue, + OperandTraits<ExtractValueConstantExpr>::op_end(this) + - (IdxList.size()+1), + IdxList.size()+1) { + OperandList[0].init(Agg, this); + for (unsigned i = 0, E = IdxList.size(); i != E; ++i) + OperandList[i+1].init(IdxList[i], this); +} + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractValueConstantExpr, Value) + +template <> +struct OperandTraits<InsertValueConstantExpr> : VariadicOperandTraits<2> { +}; + +InsertValueConstantExpr::InsertValueConstantExpr + (Constant *Agg, Constant *Val, + const std::vector<Constant*> &IdxList, + const Type *DestTy) + : ConstantExpr(DestTy, Instruction::InsertValue, + OperandTraits<InsertValueConstantExpr>::op_end(this) + - (IdxList.size()+2), + IdxList.size()+2) { + OperandList[0].init(Agg, this); + OperandList[1].init(Val, this); + for (unsigned i = 0, E = IdxList.size(); i != E; ++i) + OperandList[i+2].init(IdxList[i], this); +} + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueConstantExpr, Value) + template <> struct OperandTraits<GetElementPtrConstantExpr> : VariadicOperandTraits<1> { @@ -752,11 +828,36 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const { Op1 = (OpNo == 1) ? Op : getOperand(1); Op2 = (OpNo == 2) ? Op : getOperand(2); return ConstantExpr::getShuffleVector(Op0, Op1, Op2); + case Instruction::InsertValue: { + SmallVector<Constant*, 8> Ops; + Ops.resize(getNumOperands()-2); + for (unsigned i = 2, e = getNumOperands(); i != e; ++i) + Ops[i-2] = getOperand(i); + if (OpNo == 0) + return ConstantExpr::getInsertValue(Op, getOperand(1), + &Ops[0], Ops.size()); + if (OpNo == 1) + return ConstantExpr::getInsertValue(getOperand(0), Op, + &Ops[0], Ops.size()); + Ops[OpNo-2] = Op; + return ConstantExpr::getInsertValue(getOperand(0), getOperand(1), + &Ops[0], Ops.size()); + } + case Instruction::ExtractValue: { + SmallVector<Constant*, 8> Ops; + Ops.resize(getNumOperands()-1); + for (unsigned i = 1, e = getNumOperands(); i != e; ++i) + Ops[i-1] = getOperand(i); + if (OpNo == 0) + return ConstantExpr::getExtractValue(Op, &Ops[0], Ops.size()); + Ops[OpNo-1] = Op; + return ConstantExpr::getExtractValue(getOperand(0), &Ops[0], Ops.size()); + } case Instruction::GetElementPtr: { SmallVector<Constant*, 8> Ops; - Ops.resize(getNumOperands()); + Ops.resize(getNumOperands()-1); for (unsigned i = 1, e = getNumOperands(); i != e; ++i) - Ops[i] = getOperand(i); + Ops[i-1] = getOperand(i); if (OpNo == 0) return ConstantExpr::getGetElementPtr(Op, &Ops[0], Ops.size()); Ops[OpNo-1] = Op; @@ -807,6 +908,10 @@ getWithOperands(const std::vector<Constant*> &Ops) const { return ConstantExpr::getExtractElement(Ops[0], Ops[1]); case Instruction::ShuffleVector: return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); + case Instruction::InsertValue: + return ConstantExpr::getInsertValue(Ops[0], Ops[1], &Ops[2], Ops.size()-2); + case Instruction::ExtractValue: + return ConstantExpr::getExtractValue(Ops[0], &Ops[1], Ops.size()-1); case Instruction::GetElementPtr: return ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], Ops.size()-1); case Instruction::ICmp: @@ -1564,6 +1669,15 @@ namespace llvm { if (V.opcode == Instruction::ShuffleVector) return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1], V.operands[2]); + if (V.opcode == Instruction::InsertValue) { + std::vector<Constant*> IdxList(V.operands.begin()+2, V.operands.end()); + return InsertValueConstantExpr::Create(V.operands[0], V.operands[1], + IdxList, Ty); + } + if (V.opcode == Instruction::ExtractValue) { + std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end()); + return ExtractValueConstantExpr::Create(V.operands[0], IdxList, Ty); + } if (V.opcode == Instruction::GetElementPtr) { std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end()); return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty); @@ -1975,9 +2089,10 @@ Constant *ConstantExpr::getSelectTy(const Type *ReqTy, Constant *C, Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C, Value* const *Idxs, unsigned NumIdx) { - assert(GetElementPtrInst::getIndexedType(C->getType(), - Idxs, Idxs+NumIdx, true) - && "GEP indices invalid!"); + assert(GetElementPtrInst::getIndexedType(C->getType(), Idxs, + Idxs+NumIdx) == + cast<PointerType>(ReqTy)->getElementType() && + "GEP indices invalid!"); if (Constant *FC = ConstantFoldGetElementPtr(C, (Constant**)Idxs, NumIdx)) return FC; // Fold a few common cases... @@ -1998,7 +2113,7 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs, unsigned NumIdx) { // Get the result type of the getelementptr! const Type *Ty = - GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx, true); + GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx); assert(Ty && "GEP indices invalid!"); unsigned As = cast<PointerType>(C->getType())->getAddressSpace(); return getGetElementPtrTy(PointerType::get(Ty, As), C, Idxs, NumIdx); @@ -2181,6 +2296,76 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, return getShuffleVectorTy(V1->getType(), V1, V2, Mask); } +Constant *ConstantExpr::getInsertValueTy(const Type *ReqTy, Constant *Agg, + Constant *Val, + Constant *const *Idxs, unsigned NumIdx) { + assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs, + Idxs+NumIdx) == Val->getType() && + "insertvalue indices invalid!"); + assert(Agg->getType() == ReqTy && + "insertvalue type invalid!"); + + if (Constant *FC = ConstantFoldInsertValue(Agg, Val, Idxs, NumIdx)) + return FC; // Fold a few common cases... + + assert(isa<PointerType>(Agg->getType()) && + "Non-pointer type for constant InsertValue expression"); + // Look up the constant in the table first to ensure uniqueness + std::vector<Constant*> ArgVec; + ArgVec.reserve(NumIdx+2); + ArgVec.push_back(Agg); + ArgVec.push_back(Val); + for (unsigned i = 0; i != NumIdx; ++i) + ArgVec.push_back(cast<Constant>(Idxs[i])); + const ExprMapKeyType Key(Instruction::InsertValue, ArgVec); + return ExprConstants->getOrCreate(ReqTy, Key); +} + +Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val, + Constant* const *IdxList, unsigned NumIdx) { + assert((isa<StructType>(Agg->getType()) || isa<ArrayType>(Agg->getType()) || + isa<VectorType>(Agg->getType())) && + "Tried to create insertelement operation on non-aggregate type!"); + + const Type *ReqTy = + ExtractValueInst::getIndexedType(Agg->getType(), IdxList, IdxList+NumIdx); + assert(ReqTy && "insertvalue indices invalid!"); + return getInsertValueTy(ReqTy, Agg, Val, IdxList, NumIdx); +} + +Constant *ConstantExpr::getExtractValueTy(const Type *ReqTy, Constant *Agg, + Constant *const *Idxs, unsigned NumIdx) { + assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs, + Idxs+NumIdx) == ReqTy && + "extractvalue indices invalid!"); + + if (Constant *FC = ConstantFoldExtractValue(Agg, Idxs, NumIdx)) + return FC; // Fold a few common cases... + + assert(isa<PointerType>(Agg->getType()) && + "Non-pointer type for constant ExtractValue expression"); + // Look up the constant in the table first to ensure uniqueness + std::vector<Constant*> ArgVec; + ArgVec.reserve(NumIdx+1); + ArgVec.push_back(Agg); + for (unsigned i = 0; i != NumIdx; ++i) + ArgVec.push_back(cast<Constant>(Idxs[i])); + const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec); + return ExprConstants->getOrCreate(ReqTy, Key); +} + +Constant *ConstantExpr::getExtractValue(Constant *Agg, + Constant* const *IdxList, unsigned NumIdx) { + assert((isa<StructType>(Agg->getType()) || isa<ArrayType>(Agg->getType()) || + isa<VectorType>(Agg->getType())) && + "Tried to create extractelement operation on non-aggregate type!"); + + const Type *ReqTy = + ExtractValueInst::getIndexedType(Agg->getType(), IdxList, IdxList+NumIdx); + assert(ReqTy && "extractvalue indices invalid!"); + return getExtractValueTy(ReqTy, Agg, IdxList, NumIdx); +} + Constant *ConstantExpr::getZeroValueForNegationExpr(const Type *Ty) { if (const VectorType *PTy = dyn_cast<VectorType>(Ty)) if (PTy->getElementType()->isFloatingPoint()) { @@ -2406,6 +2591,34 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, } Replacement = ConstantExpr::getGetElementPtr(Pointer, &Indices[0], Indices.size()); + } else if (getOpcode() == Instruction::ExtractValue) { + SmallVector<Constant*, 8> Indices; + Constant *Agg = getOperand(0); + Indices.reserve(getNumOperands()-1); + if (Agg == From) Agg = To; + + for (unsigned i = 1, e = getNumOperands(); i != e; ++i) { + Constant *Val = getOperand(i); + if (Val == From) Val = To; + Indices.push_back(Val); + } + Replacement = ConstantExpr::getExtractValue(Agg, + &Indices[0], Indices.size()); + } else if (getOpcode() == Instruction::InsertValue) { + SmallVector<Constant*, 8> Indices; + Constant *Agg = getOperand(0); + Constant *Val = getOperand(1); + Indices.reserve(getNumOperands()-2); + if (Agg == From) Agg = To; + if (Val == From) Val = To; + + for (unsigned i = 2, e = getNumOperands(); i != e; ++i) { + Constant *Val = getOperand(i); + if (Val == From) Val = To; + Indices.push_back(Val); + } + Replacement = ConstantExpr::getInsertValue(Agg, Val, + &Indices[0], Indices.size()); } else if (isCast()) { assert(getOperand(0) == From && "Cast only has one use!"); Replacement = ConstantExpr::getCast(getOpcode(), To, getType()); diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 473e9fa..c54815a 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -1038,41 +1038,16 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx, // const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value* const *Idxs, - unsigned NumIdx, - bool AllowCompositeLeaf) { - if (!isa<PointerType>(Ptr)) return 0; // Type isn't a pointer type! + unsigned NumIdx) { + const PointerType *PTy = dyn_cast<PointerType>(Ptr); + if (!PTy) return 0; // Type isn't a pointer type! + const Type *Agg = PTy->getElementType(); // Handle the special case of the empty set index set... - if (NumIdx == 0) { - if (AllowCompositeLeaf || - cast<PointerType>(Ptr)->getElementType()->isFirstClassType()) - return cast<PointerType>(Ptr)->getElementType(); - else - return 0; - } - - unsigned CurIdx = 0; - while (const CompositeType *CT = dyn_cast<CompositeType>(Ptr)) { - if (NumIdx == CurIdx) { - if (AllowCompositeLeaf || CT->isFirstClassType()) return Ptr; - return 0; // Can't load a whole structure or array!?!? - } + if (NumIdx == 0) + return Agg; - Value *Index = Idxs[CurIdx++]; - if (isa<PointerType>(CT) && CurIdx != 1) - return 0; // Can only index into pointer types at the first index! - if (!CT->indexValid(Index)) return 0; - Ptr = CT->getTypeAtIndex(Index); - - // If the new type forwards to another type, then it is in the middle - // of being refined to another type (and hence, may have dropped all - // references to what it was using before). So, use the new forwarded - // type. - if (const Type * Ty = Ptr->getForwardedType()) { - Ptr = Ty; - } - } - return CurIdx == NumIdx ? Ptr : 0; + return ExtractValueInst::getIndexedType(Agg, Idxs+1, Idxs+NumIdx); } const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) { @@ -1345,6 +1320,36 @@ int ShuffleVectorInst::getMaskValue(unsigned i) const { return cast<ConstantInt>(MaskCV->getOperand(i))->getZExtValue(); } +//===----------------------------------------------------------------------===// +// ExtractValueInst Class +//===----------------------------------------------------------------------===// + +// getIndexedType - Returns the type of the element that would be extracted +// with an extractvalue instruction with the specified parameters. +// +// A null type is returned if the indices are invalid for the specified +// pointer type. +// +const Type* ExtractValueInst::getIndexedType(const Type *Agg, + Value* const *Idxs, + unsigned NumIdx) { + unsigned CurIdx = 0; + for (; CurIdx != NumIdx; ++CurIdx) { + const CompositeType *CT = dyn_cast<CompositeType>(Agg); + if (!CT) return 0; + Value *Index = Idxs[CurIdx]; + if (!CT->indexValid(Index)) return 0; + Agg = CT->getTypeAtIndex(Index); + + // If the new type forwards to another type, then it is in the middle + // of being refined to another type (and hence, may have dropped all + // references to what it was using before). So, use the new forwarded + // type. + if (const Type *Ty = Agg->getForwardedType()) + Agg = Ty; + } + return CurIdx == NumIdx ? Agg : 0; +} //===----------------------------------------------------------------------===// // BinaryOperator Class diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 78158be..bfa2e65 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -1045,7 +1045,7 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { SmallVector<Value*, 16> Idxs(GEP.idx_begin(), GEP.idx_end()); const Type *ElTy = GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(), - Idxs.begin(), Idxs.end(), true); + Idxs.begin(), Idxs.end()); Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP); Assert2(isa<PointerType>(GEP.getType()) && cast<PointerType>(GEP.getType())->getElementType() == ElTy, |