From d62a1e966c5b4ffb4ee904c20fe3026f59d12b85 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Tue, 21 Apr 2015 23:26:57 +0000 Subject: [PATCH] [opaque pointer type] Avoid using PointerType::getElementType for a few cases of CallInst Calls to llvm::Value::mutateType are becoming extra-sensitive now that instructions have extra type information that will not be derived from operands or result type (alloca, gep, load, call/invoke, etc... ). The special-handling for mutateType will get more complicated as this work continues - it might be worth making mutateType virtual & pushing the complexity down into the classes that need special handling. But with only two significant uses of mutateType (vectorization and linking) this seems OK for now. Totally open to ideas/suggestions/improvements, of course. With this, and a bunch of exceptions, we can roundtrip an indirect call site through bitcode and IR. (a direct call site is actually trickier... I haven't figured out how to deal with the IR deserializer's lazy construction of Function/GlobalVariable decl's based on the type of the entity which means looking through the "pointer to T" type referring to the global) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235458 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/CallSite.h | 8 +++ include/llvm/IR/Instructions.h | 71 +++++++++++++++++++----- lib/AsmParser/LLParser.cpp | 2 +- lib/Bitcode/Reader/BitcodeReader.cpp | 13 ++--- lib/IR/Instructions.cpp | 37 ++++++------ lib/IR/Verifier.cpp | 6 +- lib/Transforms/Utils/ValueMapper.cpp | 13 ++++- lib/Transforms/Vectorize/BBVectorize.cpp | 12 +++- 8 files changed, 116 insertions(+), 46 deletions(-) diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index ebace3395ac..55fa0b5bd5e 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -194,6 +194,14 @@ public: CALLSITE_DELEGATE_SETTER(setCallingConv(CC)); } + FunctionType *getFunctionType() const { + CALLSITE_DELEGATE_GETTER(getFunctionType()); + } + + void mutateFunctionType(FunctionType *Ty) const { + CALLSITE_DELEGATE_SETTER(mutateFunctionType(Ty)); + } + /// getAttributes/setAttributes - get or set the parameter attributes of /// the call. const AttributeSet &getAttributes() const { diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 2571faf3836..7c60945fad6 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -1284,14 +1284,26 @@ public: /// class CallInst : public Instruction { AttributeSet AttributeList; ///< parameter attributes for call + FunctionType *FTy; CallInst(const CallInst &CI); - void init(Value *Func, ArrayRef Args, const Twine &NameStr); + void init(Value *Func, ArrayRef Args, const Twine &NameStr) { + init(cast( + cast(Func->getType())->getElementType()), + Func, Args, NameStr); + } + void init(FunctionType *FTy, Value *Func, ArrayRef Args, + const Twine &NameStr); void init(Value *Func, const Twine &NameStr); /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments - inline CallInst(Value *Func, ArrayRef Args, + inline CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, const Twine &NameStr, Instruction *InsertBefore); + inline CallInst(Value *Func, ArrayRef Args, const Twine &NameStr, + Instruction *InsertBefore) + : CallInst(cast( + cast(Func->getType())->getElementType()), + Func, Args, NameStr, InsertBefore) {} /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments @@ -1308,8 +1320,15 @@ public: ArrayRef Args, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { - return new(unsigned(Args.size() + 1)) - CallInst(Func, Args, NameStr, InsertBefore); + return Create(cast( + cast(Func->getType())->getElementType()), + Func, Args, NameStr, InsertBefore); + } + static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef Args, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + return new (unsigned(Args.size() + 1)) + CallInst(Ty, Func, Args, NameStr, InsertBefore); } static CallInst *Create(Value *Func, ArrayRef Args, @@ -1347,9 +1366,11 @@ public: ~CallInst() override; - FunctionType *getFunctionType() const { - return cast( - cast(getCalledValue()->getType())->getElementType()); + FunctionType *getFunctionType() const { return FTy; } + + void mutateFunctionType(FunctionType *FTy) { + mutateType(FTy->getReturnType()); + this->FTy = FTy; } // Note that 'musttail' implies 'tail'. @@ -1533,6 +1554,14 @@ public: /// setCalledFunction - Set the function called. void setCalledFunction(Value* Fn) { + setCalledFunction( + cast(cast(Fn->getType())->getElementType()), + Fn); + } + void setCalledFunction(FunctionType *FTy, Value *Fn) { + this->FTy = FTy; + assert(FTy == cast( + cast(Fn->getType())->getElementType())); Op<-1>() = Fn; } @@ -1573,14 +1602,12 @@ CallInst::CallInst(Value *Func, ArrayRef Args, init(Func, Args, NameStr); } -CallInst::CallInst(Value *Func, ArrayRef Args, +CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, const Twine &NameStr, Instruction *InsertBefore) - : Instruction(cast(cast(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Call, - OperandTraits::op_end(this) - (Args.size() + 1), - unsigned(Args.size() + 1), InsertBefore) { - init(Func, Args, NameStr); + : Instruction(Ty->getReturnType(), Instruction::Call, + OperandTraits::op_end(this) - (Args.size() + 1), + unsigned(Args.size() + 1), InsertBefore) { + init(Ty, Func, Args, NameStr); } @@ -3034,6 +3061,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) /// class InvokeInst : public TerminatorInst { AttributeSet AttributeList; + FunctionType *FTy; InvokeInst(const InvokeInst &BI); void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, const Twine &NameStr); @@ -3074,6 +3102,13 @@ public: /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + FunctionType *getFunctionType() const { return FTy; } + + void mutateFunctionType(FunctionType *FTy) { + mutateType(FTy->getReturnType()); + this->FTy = FTy; + } + /// getNumArgOperands - Return the number of invoke arguments. /// unsigned getNumArgOperands() const { return getNumOperands() - 3; } @@ -3223,6 +3258,14 @@ public: /// setCalledFunction - Set the function called. void setCalledFunction(Value* Fn) { + setCalledFunction( + cast(cast(Fn->getType())->getElementType()), + Fn); + } + void setCalledFunction(FunctionType *FTy, Value *Fn) { + this->FTy = FTy; + assert(FTy == cast( + cast(Fn->getType())->getElementType())); Op<-3>() = Fn; } diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index be098c1b128..2e8008b96e7 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -5224,7 +5224,7 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS, // Finish off the Attribute and check them AttributeSet PAL = AttributeSet::get(Context, Attrs); - CallInst *CI = CallInst::Create(Callee, Args); + CallInst *CI = CallInst::Create(Ty, Callee, Args); CI->setTailCallKind(TCK); CI->setCallingConv(CC); CI->setAttributes(PAL); diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index bc78a71efad..f3446b73f93 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -4184,12 +4184,11 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) { PointerType *OpTy = dyn_cast(Callee->getType()); if (!OpTy) return Error("Callee is not a pointer type"); - FunctionType *PFTy = dyn_cast(OpTy->getElementType()); - if (!PFTy) - return Error("Callee is not of pointer to function type"); - if (!FTy) - FTy = PFTy; - if (PFTy != FTy) + if (!FTy) { + FTy = dyn_cast(OpTy->getElementType()); + if (!FTy) + return Error("Callee is not of pointer to function type"); + } else if (OpTy->getElementType() != FTy) return Error("Explicit call type does not match pointee type of " "callee operand"); if (Record.size() < FTy->getNumParams() + OpNum) @@ -4220,7 +4219,7 @@ std::error_code BitcodeReader::ParseFunctionBody(Function *F) { } } - I = CallInst::Create(Callee, Args); + I = CallInst::Create(FTy, Callee, Args); InstructionList.push_back(I); cast(I)->setCallingConv( static_cast((~(1U << 14) & CCInfo) >> 1)); diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index b2898429239..aa878ea436e 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -263,14 +263,13 @@ void LandingPadInst::addClause(Constant *Val) { CallInst::~CallInst() { } -void CallInst::init(Value *Func, ArrayRef Args, const Twine &NameStr) { +void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef Args, + const Twine &NameStr) { + this->FTy = FTy; assert(NumOperands == Args.size() + 1 && "NumOperands not set up?"); Op<-1>() = Func; #ifndef NDEBUG - FunctionType *FTy = - cast(cast(Func->getType())->getElementType()); - assert((Args.size() == FTy->getNumParams() || (FTy->isVarArg() && Args.size() > FTy->getNumParams())) && "Calling a function with bad signature!"); @@ -286,15 +285,12 @@ void CallInst::init(Value *Func, ArrayRef Args, const Twine &NameStr) { } void CallInst::init(Value *Func, const Twine &NameStr) { + FTy = + cast(cast(Func->getType())->getElementType()); assert(NumOperands == 1 && "NumOperands not set up?"); Op<-1>() = Func; -#ifndef NDEBUG - FunctionType *FTy = - cast(cast(Func->getType())->getElementType()); - assert(FTy->getNumParams() == 0 && "Calling a function with bad signature"); -#endif setName(NameStr); } @@ -320,10 +316,10 @@ CallInst::CallInst(Value *Func, const Twine &Name, } CallInst::CallInst(const CallInst &CI) - : Instruction(CI.getType(), Instruction::Call, - OperandTraits::op_end(this) - CI.getNumOperands(), - CI.getNumOperands()) { - setAttributes(CI.getAttributes()); + : Instruction(CI.getType(), Instruction::Call, + OperandTraits::op_end(this) - CI.getNumOperands(), + CI.getNumOperands()), + AttributeList(CI.AttributeList), FTy(CI.FTy) { setTailCallKind(CI.getTailCallKind()); setCallingConv(CI.getCallingConv()); @@ -543,15 +539,14 @@ Instruction* CallInst::CreateFree(Value* Source, BasicBlock *InsertAtEnd) { void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, const Twine &NameStr) { + FTy = cast(cast(Fn->getType())->getElementType()); + assert(NumOperands == 3 + Args.size() && "NumOperands not set up?"); Op<-3>() = Fn; Op<-2>() = IfNormal; Op<-1>() = IfException; #ifndef NDEBUG - FunctionType *FTy = - cast(cast(Fn->getType())->getElementType()); - assert(((Args.size() == FTy->getNumParams()) || (FTy->isVarArg() && Args.size() > FTy->getNumParams())) && "Invoking a function with bad signature"); @@ -567,11 +562,11 @@ void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, } InvokeInst::InvokeInst(const InvokeInst &II) - : TerminatorInst(II.getType(), Instruction::Invoke, - OperandTraits::op_end(this) - - II.getNumOperands(), - II.getNumOperands()) { - setAttributes(II.getAttributes()); + : TerminatorInst(II.getType(), Instruction::Invoke, + OperandTraits::op_end(this) - + II.getNumOperands(), + II.getNumOperands()), + AttributeList(II.AttributeList), FTy(II.FTy) { setCallingConv(II.getCallingConv()); std::copy(II.op_begin(), II.op_end(), op_begin()); SubclassOptionalData = II.SubclassOptionalData; diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index e14f1036912..7001c556d20 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -2120,7 +2120,11 @@ void Verifier::VerifyCallSite(CallSite CS) { Assert(FPTy->getElementType()->isFunctionTy(), "Called function is not pointer to function type!", I); - FunctionType *FTy = cast(FPTy->getElementType()); + + Assert(FPTy->getElementType() == CS.getFunctionType(), + "Called function is not the same type as the call!", I); + + FunctionType *FTy = CS.getFunctionType(); // Verify that the correct number of arguments are being passed if (FTy->isVarArg()) diff --git a/lib/Transforms/Utils/ValueMapper.cpp b/lib/Transforms/Utils/ValueMapper.cpp index 54c76887234..a70d6d769b7 100644 --- a/lib/Transforms/Utils/ValueMapper.cpp +++ b/lib/Transforms/Utils/ValueMapper.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/ValueMapper.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" @@ -384,6 +385,16 @@ void llvm::RemapInstruction(Instruction *I, ValueToValueMapTy &VMap, } // If the instruction's type is being remapped, do so now. - if (TypeMapper) + if (auto CS = CallSite(I)) { + SmallVector Tys; + FunctionType *Old = CS.getFunctionType(); + unsigned NumOld = Old->getNumParams(); + assert(NumOld <= CS.arg_size()); + for (unsigned i = 0; i != NumOld; ++i) + Tys.push_back(CS.getArgument(i)->getType()); + CS.mutateFunctionType(FunctionType::get( + TypeMapper ? TypeMapper->remapType(I->getType()) : I->getType(), Tys, + Old->isVarArg())); + } else if (TypeMapper) I->mutateType(TypeMapper->remapType(I->getType())); } diff --git a/lib/Transforms/Vectorize/BBVectorize.cpp b/lib/Transforms/Vectorize/BBVectorize.cpp index 29fb01f1b2e..6f0180e7db0 100644 --- a/lib/Transforms/Vectorize/BBVectorize.cpp +++ b/lib/Transforms/Vectorize/BBVectorize.cpp @@ -3103,7 +3103,17 @@ namespace { else if (H->hasName()) K->takeName(H); - if (!isa(K)) + if (auto CS = CallSite(K)) { + SmallVector Tys; + FunctionType *Old = CS.getFunctionType(); + unsigned NumOld = Old->getNumParams(); + assert(NumOld <= ReplacedOperands.size()); + for (unsigned i = 0; i != NumOld; ++i) + Tys.push_back(ReplacedOperands[i]->getType()); + CS.mutateFunctionType( + FunctionType::get(getVecTypeForPair(L->getType(), H->getType()), + Tys, Old->isVarArg())); + } else if (!isa(K)) K->mutateType(getVecTypeForPair(L->getType(), H->getType())); unsigned KnownIDs[] = { -- 2.34.1