diff options
Diffstat (limited to 'lib/IR/Instructions.cpp')
| -rw-r--r-- | lib/IR/Instructions.cpp | 722 |
1 files changed, 421 insertions, 301 deletions
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index 32db918dab97..06b46724a87f 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -27,6 +27,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" @@ -65,50 +66,7 @@ AllocaInst::getAllocationSizeInBits(const DataLayout &DL) const { //===----------------------------------------------------------------------===// User::op_iterator CallSite::getCallee() const { - Instruction *II(getInstruction()); - return isCall() - ? cast<CallInst>(II)->op_end() - 1 // Skip Callee - : cast<InvokeInst>(II)->op_end() - 3; // Skip BB, BB, Callee -} - -//===----------------------------------------------------------------------===// -// TerminatorInst Class -//===----------------------------------------------------------------------===// - -unsigned TerminatorInst::getNumSuccessors() const { - switch (getOpcode()) { -#define HANDLE_TERM_INST(N, OPC, CLASS) \ - case Instruction::OPC: \ - return static_cast<const CLASS *>(this)->getNumSuccessors(); -#include "llvm/IR/Instruction.def" - default: - break; - } - llvm_unreachable("not a terminator"); -} - -BasicBlock *TerminatorInst::getSuccessor(unsigned idx) const { - switch (getOpcode()) { -#define HANDLE_TERM_INST(N, OPC, CLASS) \ - case Instruction::OPC: \ - return static_cast<const CLASS *>(this)->getSuccessor(idx); -#include "llvm/IR/Instruction.def" - default: - break; - } - llvm_unreachable("not a terminator"); -} - -void TerminatorInst::setSuccessor(unsigned idx, BasicBlock *B) { - switch (getOpcode()) { -#define HANDLE_TERM_INST(N, OPC, CLASS) \ - case Instruction::OPC: \ - return static_cast<CLASS *>(this)->setSuccessor(idx, B); -#include "llvm/IR/Instruction.def" - default: - break; - } - llvm_unreachable("not a terminator"); + return cast<CallBase>(getInstruction())->op_end() - 1; } //===----------------------------------------------------------------------===// @@ -294,6 +252,112 @@ void LandingPadInst::addClause(Constant *Val) { } //===----------------------------------------------------------------------===// +// CallBase Implementation +//===----------------------------------------------------------------------===// + +Function *CallBase::getCaller() { return getParent()->getParent(); } + +bool CallBase::isIndirectCall() const { + const Value *V = getCalledValue(); + if (isa<Function>(V) || isa<Constant>(V)) + return false; + if (const CallInst *CI = dyn_cast<CallInst>(this)) + if (CI->isInlineAsm()) + return false; + return true; +} + +Intrinsic::ID CallBase::getIntrinsicID() const { + if (auto *F = getCalledFunction()) + return F->getIntrinsicID(); + return Intrinsic::not_intrinsic; +} + +bool CallBase::isReturnNonNull() const { + if (hasRetAttr(Attribute::NonNull)) + return true; + + if (getDereferenceableBytes(AttributeList::ReturnIndex) > 0 && + !NullPointerIsDefined(getCaller(), + getType()->getPointerAddressSpace())) + return true; + + return false; +} + +Value *CallBase::getReturnedArgOperand() const { + unsigned Index; + + if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index) + return getArgOperand(Index - AttributeList::FirstArgIndex); + if (const Function *F = getCalledFunction()) + if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) && + Index) + return getArgOperand(Index - AttributeList::FirstArgIndex); + + return nullptr; +} + +bool CallBase::hasRetAttr(Attribute::AttrKind Kind) const { + if (Attrs.hasAttribute(AttributeList::ReturnIndex, Kind)) + return true; + + // Look at the callee, if available. + if (const Function *F = getCalledFunction()) + return F->getAttributes().hasAttribute(AttributeList::ReturnIndex, Kind); + return false; +} + +/// Determine whether the argument or parameter has the given attribute. +bool CallBase::paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const { + assert(ArgNo < getNumArgOperands() && "Param index out of bounds!"); + + if (Attrs.hasParamAttribute(ArgNo, Kind)) + return true; + if (const Function *F = getCalledFunction()) + return F->getAttributes().hasParamAttribute(ArgNo, Kind); + return false; +} + +bool CallBase::hasFnAttrOnCalledFunction(Attribute::AttrKind Kind) const { + if (const Function *F = getCalledFunction()) + return F->getAttributes().hasAttribute(AttributeList::FunctionIndex, Kind); + return false; +} + +bool CallBase::hasFnAttrOnCalledFunction(StringRef Kind) const { + if (const Function *F = getCalledFunction()) + return F->getAttributes().hasAttribute(AttributeList::FunctionIndex, Kind); + return false; +} + +CallBase::op_iterator +CallBase::populateBundleOperandInfos(ArrayRef<OperandBundleDef> Bundles, + const unsigned BeginIndex) { + auto It = op_begin() + BeginIndex; + for (auto &B : Bundles) + It = std::copy(B.input_begin(), B.input_end(), It); + + auto *ContextImpl = getContext().pImpl; + auto BI = Bundles.begin(); + unsigned CurrentIndex = BeginIndex; + + for (auto &BOI : bundle_op_infos()) { + assert(BI != Bundles.end() && "Incorrect allocation?"); + + BOI.Tag = ContextImpl->getOrInsertBundleTag(BI->getTag()); + BOI.Begin = CurrentIndex; + BOI.End = CurrentIndex + BI->input_size(); + CurrentIndex = BOI.End; + BI++; + } + + assert(BI == Bundles.end() && "Incorrect allocation?"); + + return It; +} + +//===----------------------------------------------------------------------===// // CallInst Implementation //===----------------------------------------------------------------------===// @@ -302,7 +366,7 @@ void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args, this->FTy = FTy; assert(getNumOperands() == Args.size() + CountBundleInputs(Bundles) + 1 && "NumOperands not set up?"); - Op<-1>() = Func; + setCalledOperand(Func); #ifndef NDEBUG assert((Args.size() == FTy->getNumParams() || @@ -315,7 +379,7 @@ void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args, "Calling a function with a bad signature!"); #endif - std::copy(Args.begin(), Args.end(), op_begin()); + llvm::copy(Args, op_begin()); auto It = populateBundleOperandInfos(Bundles, Args.size()); (void)It; @@ -324,43 +388,34 @@ void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args, setName(NameStr); } -void CallInst::init(Value *Func, const Twine &NameStr) { - FTy = - cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType()); +void CallInst::init(FunctionType *FTy, Value *Func, const Twine &NameStr) { + this->FTy = FTy; assert(getNumOperands() == 1 && "NumOperands not set up?"); - Op<-1>() = Func; + setCalledOperand(Func); assert(FTy->getNumParams() == 0 && "Calling a function with bad signature"); setName(NameStr); } -CallInst::CallInst(Value *Func, const Twine &Name, Instruction *InsertBefore) - : CallBase<CallInst>( - cast<FunctionType>( - cast<PointerType>(Func->getType())->getElementType()) - ->getReturnType(), - Instruction::Call, - OperandTraits<CallBase<CallInst>>::op_end(this) - 1, 1, - InsertBefore) { - init(Func, Name); +CallInst::CallInst(FunctionType *Ty, Value *Func, const Twine &Name, + Instruction *InsertBefore) + : CallBase(Ty->getReturnType(), Instruction::Call, + OperandTraits<CallBase>::op_end(this) - 1, 1, InsertBefore) { + init(Ty, Func, Name); } -CallInst::CallInst(Value *Func, const Twine &Name, BasicBlock *InsertAtEnd) - : CallBase<CallInst>( - cast<FunctionType>( - cast<PointerType>(Func->getType())->getElementType()) - ->getReturnType(), - Instruction::Call, - OperandTraits<CallBase<CallInst>>::op_end(this) - 1, 1, InsertAtEnd) { - init(Func, Name); +CallInst::CallInst(FunctionType *Ty, Value *Func, const Twine &Name, + BasicBlock *InsertAtEnd) + : CallBase(Ty->getReturnType(), Instruction::Call, + OperandTraits<CallBase>::op_end(this) - 1, 1, InsertAtEnd) { + init(Ty, Func, Name); } CallInst::CallInst(const CallInst &CI) - : CallBase<CallInst>(CI.Attrs, CI.FTy, CI.getType(), Instruction::Call, - OperandTraits<CallBase<CallInst>>::op_end(this) - - CI.getNumOperands(), - CI.getNumOperands()) { + : CallBase(CI.Attrs, CI.FTy, CI.getType(), Instruction::Call, + OperandTraits<CallBase>::op_end(this) - CI.getNumOperands(), + CI.getNumOperands()) { setTailCallKind(CI.getTailCallKind()); setCallingConv(CI.getCallingConv()); @@ -600,11 +655,12 @@ void InvokeInst::init(FunctionType *FTy, Value *Fn, BasicBlock *IfNormal, const Twine &NameStr) { this->FTy = FTy; - assert(getNumOperands() == 3 + Args.size() + CountBundleInputs(Bundles) && + assert((int)getNumOperands() == + ComputeNumOperands(Args.size(), CountBundleInputs(Bundles)) && "NumOperands not set up?"); - Op<-3>() = Fn; - Op<-2>() = IfNormal; - Op<-1>() = IfException; + setNormalDest(IfNormal); + setUnwindDest(IfException); + setCalledOperand(Fn); #ifndef NDEBUG assert(((Args.size() == FTy->getNumParams()) || @@ -617,7 +673,7 @@ void InvokeInst::init(FunctionType *FTy, Value *Fn, BasicBlock *IfNormal, "Invoking a function with a bad signature!"); #endif - std::copy(Args.begin(), Args.end(), op_begin()); + llvm::copy(Args, op_begin()); auto It = populateBundleOperandInfos(Bundles, Args.size()); (void)It; @@ -627,10 +683,9 @@ void InvokeInst::init(FunctionType *FTy, Value *Fn, BasicBlock *IfNormal, } InvokeInst::InvokeInst(const InvokeInst &II) - : CallBase<InvokeInst>(II.Attrs, II.FTy, II.getType(), Instruction::Invoke, - OperandTraits<CallBase<InvokeInst>>::op_end(this) - - II.getNumOperands(), - II.getNumOperands()) { + : CallBase(II.Attrs, II.FTy, II.getType(), Instruction::Invoke, + OperandTraits<CallBase>::op_end(this) - II.getNumOperands(), + II.getNumOperands()) { setCallingConv(II.getCallingConv()); std::copy(II.op_begin(), II.op_end(), op_begin()); std::copy(II.bundle_op_info_begin(), II.bundle_op_info_end(), @@ -662,55 +717,53 @@ LandingPadInst *InvokeInst::getLandingPadInst() const { //===----------------------------------------------------------------------===// ReturnInst::ReturnInst(const ReturnInst &RI) - : TerminatorInst(Type::getVoidTy(RI.getContext()), Instruction::Ret, - OperandTraits<ReturnInst>::op_end(this) - - RI.getNumOperands(), - RI.getNumOperands()) { + : Instruction(Type::getVoidTy(RI.getContext()), Instruction::Ret, + OperandTraits<ReturnInst>::op_end(this) - RI.getNumOperands(), + RI.getNumOperands()) { if (RI.getNumOperands()) Op<0>() = RI.Op<0>(); SubclassOptionalData = RI.SubclassOptionalData; } ReturnInst::ReturnInst(LLVMContext &C, Value *retVal, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(C), Instruction::Ret, - OperandTraits<ReturnInst>::op_end(this) - !!retVal, !!retVal, - InsertBefore) { + : Instruction(Type::getVoidTy(C), Instruction::Ret, + OperandTraits<ReturnInst>::op_end(this) - !!retVal, !!retVal, + InsertBefore) { if (retVal) Op<0>() = retVal; } ReturnInst::ReturnInst(LLVMContext &C, Value *retVal, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(C), Instruction::Ret, - OperandTraits<ReturnInst>::op_end(this) - !!retVal, !!retVal, - InsertAtEnd) { + : Instruction(Type::getVoidTy(C), Instruction::Ret, + OperandTraits<ReturnInst>::op_end(this) - !!retVal, !!retVal, + InsertAtEnd) { if (retVal) Op<0>() = retVal; } ReturnInst::ReturnInst(LLVMContext &Context, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(Context), Instruction::Ret, - OperandTraits<ReturnInst>::op_end(this), 0, InsertAtEnd) { -} + : Instruction(Type::getVoidTy(Context), Instruction::Ret, + OperandTraits<ReturnInst>::op_end(this), 0, InsertAtEnd) {} //===----------------------------------------------------------------------===// // ResumeInst Implementation //===----------------------------------------------------------------------===// ResumeInst::ResumeInst(const ResumeInst &RI) - : TerminatorInst(Type::getVoidTy(RI.getContext()), Instruction::Resume, - OperandTraits<ResumeInst>::op_begin(this), 1) { + : Instruction(Type::getVoidTy(RI.getContext()), Instruction::Resume, + OperandTraits<ResumeInst>::op_begin(this), 1) { Op<0>() = RI.Op<0>(); } ResumeInst::ResumeInst(Value *Exn, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(Exn->getContext()), Instruction::Resume, - OperandTraits<ResumeInst>::op_begin(this), 1, InsertBefore) { + : Instruction(Type::getVoidTy(Exn->getContext()), Instruction::Resume, + OperandTraits<ResumeInst>::op_begin(this), 1, InsertBefore) { Op<0>() = Exn; } ResumeInst::ResumeInst(Value *Exn, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(Exn->getContext()), Instruction::Resume, - OperandTraits<ResumeInst>::op_begin(this), 1, InsertAtEnd) { + : Instruction(Type::getVoidTy(Exn->getContext()), Instruction::Resume, + OperandTraits<ResumeInst>::op_begin(this), 1, InsertAtEnd) { Op<0>() = Exn; } @@ -719,10 +772,10 @@ ResumeInst::ResumeInst(Value *Exn, BasicBlock *InsertAtEnd) //===----------------------------------------------------------------------===// CleanupReturnInst::CleanupReturnInst(const CleanupReturnInst &CRI) - : TerminatorInst(CRI.getType(), Instruction::CleanupRet, - OperandTraits<CleanupReturnInst>::op_end(this) - - CRI.getNumOperands(), - CRI.getNumOperands()) { + : Instruction(CRI.getType(), Instruction::CleanupRet, + OperandTraits<CleanupReturnInst>::op_end(this) - + CRI.getNumOperands(), + CRI.getNumOperands()) { setInstructionSubclassData(CRI.getSubclassDataFromInstruction()); Op<0>() = CRI.Op<0>(); if (CRI.hasUnwindDest()) @@ -740,19 +793,19 @@ void CleanupReturnInst::init(Value *CleanupPad, BasicBlock *UnwindBB) { CleanupReturnInst::CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()), - Instruction::CleanupRet, - OperandTraits<CleanupReturnInst>::op_end(this) - Values, - Values, InsertBefore) { + : Instruction(Type::getVoidTy(CleanupPad->getContext()), + Instruction::CleanupRet, + OperandTraits<CleanupReturnInst>::op_end(this) - Values, + Values, InsertBefore) { init(CleanupPad, UnwindBB); } CleanupReturnInst::CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB, unsigned Values, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(CleanupPad->getContext()), - Instruction::CleanupRet, - OperandTraits<CleanupReturnInst>::op_end(this) - Values, - Values, InsertAtEnd) { + : Instruction(Type::getVoidTy(CleanupPad->getContext()), + Instruction::CleanupRet, + OperandTraits<CleanupReturnInst>::op_end(this) - Values, + Values, InsertAtEnd) { init(CleanupPad, UnwindBB); } @@ -765,25 +818,25 @@ void CatchReturnInst::init(Value *CatchPad, BasicBlock *BB) { } CatchReturnInst::CatchReturnInst(const CatchReturnInst &CRI) - : TerminatorInst(Type::getVoidTy(CRI.getContext()), Instruction::CatchRet, - OperandTraits<CatchReturnInst>::op_begin(this), 2) { + : Instruction(Type::getVoidTy(CRI.getContext()), Instruction::CatchRet, + OperandTraits<CatchReturnInst>::op_begin(this), 2) { Op<0>() = CRI.Op<0>(); Op<1>() = CRI.Op<1>(); } CatchReturnInst::CatchReturnInst(Value *CatchPad, BasicBlock *BB, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet, - OperandTraits<CatchReturnInst>::op_begin(this), 2, - InsertBefore) { + : Instruction(Type::getVoidTy(BB->getContext()), Instruction::CatchRet, + OperandTraits<CatchReturnInst>::op_begin(this), 2, + InsertBefore) { init(CatchPad, BB); } CatchReturnInst::CatchReturnInst(Value *CatchPad, BasicBlock *BB, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet, - OperandTraits<CatchReturnInst>::op_begin(this), 2, - InsertAtEnd) { + : Instruction(Type::getVoidTy(BB->getContext()), Instruction::CatchRet, + OperandTraits<CatchReturnInst>::op_begin(this), 2, + InsertAtEnd) { init(CatchPad, BB); } @@ -795,8 +848,8 @@ CatchSwitchInst::CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest, unsigned NumReservedValues, const Twine &NameStr, Instruction *InsertBefore) - : TerminatorInst(ParentPad->getType(), Instruction::CatchSwitch, nullptr, 0, - InsertBefore) { + : Instruction(ParentPad->getType(), Instruction::CatchSwitch, nullptr, 0, + InsertBefore) { if (UnwindDest) ++NumReservedValues; init(ParentPad, UnwindDest, NumReservedValues + 1); @@ -806,8 +859,8 @@ CatchSwitchInst::CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest, CatchSwitchInst::CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest, unsigned NumReservedValues, const Twine &NameStr, BasicBlock *InsertAtEnd) - : TerminatorInst(ParentPad->getType(), Instruction::CatchSwitch, nullptr, 0, - InsertAtEnd) { + : Instruction(ParentPad->getType(), Instruction::CatchSwitch, nullptr, 0, + InsertAtEnd) { if (UnwindDest) ++NumReservedValues; init(ParentPad, UnwindDest, NumReservedValues + 1); @@ -815,8 +868,8 @@ CatchSwitchInst::CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest, } CatchSwitchInst::CatchSwitchInst(const CatchSwitchInst &CSI) - : TerminatorInst(CSI.getType(), Instruction::CatchSwitch, nullptr, - CSI.getNumOperands()) { + : Instruction(CSI.getType(), Instruction::CatchSwitch, nullptr, + CSI.getNumOperands()) { init(CSI.getParentPad(), CSI.getUnwindDest(), CSI.getNumOperands()); setNumHungOffUseOperands(ReservedSpace); Use *OL = getOperandList(); @@ -876,7 +929,7 @@ void CatchSwitchInst::removeHandler(handler_iterator HI) { void FuncletPadInst::init(Value *ParentPad, ArrayRef<Value *> Args, const Twine &NameStr) { assert(getNumOperands() == 1 + Args.size() && "NumOperands not set up?"); - std::copy(Args.begin(), Args.end(), op_begin()); + llvm::copy(Args, op_begin()); setParentPad(ParentPad); setName(NameStr); } @@ -914,13 +967,11 @@ FuncletPadInst::FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad, UnreachableInst::UnreachableInst(LLVMContext &Context, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(Context), Instruction::Unreachable, - nullptr, 0, InsertBefore) { -} + : Instruction(Type::getVoidTy(Context), Instruction::Unreachable, nullptr, + 0, InsertBefore) {} UnreachableInst::UnreachableInst(LLVMContext &Context, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(Context), Instruction::Unreachable, - nullptr, 0, InsertAtEnd) { -} + : Instruction(Type::getVoidTy(Context), Instruction::Unreachable, nullptr, + 0, InsertAtEnd) {} //===----------------------------------------------------------------------===// // BranchInst Implementation @@ -933,18 +984,18 @@ void BranchInst::AssertOK() { } BranchInst::BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(IfTrue->getContext()), Instruction::Br, - OperandTraits<BranchInst>::op_end(this) - 1, - 1, InsertBefore) { + : Instruction(Type::getVoidTy(IfTrue->getContext()), Instruction::Br, + OperandTraits<BranchInst>::op_end(this) - 1, 1, + InsertBefore) { assert(IfTrue && "Branch destination may not be null!"); Op<-1>() = IfTrue; } BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(IfTrue->getContext()), Instruction::Br, - OperandTraits<BranchInst>::op_end(this) - 3, - 3, InsertBefore) { + : Instruction(Type::getVoidTy(IfTrue->getContext()), Instruction::Br, + OperandTraits<BranchInst>::op_end(this) - 3, 3, + InsertBefore) { Op<-1>() = IfTrue; Op<-2>() = IfFalse; Op<-3>() = Cond; @@ -954,18 +1005,16 @@ BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, } BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(IfTrue->getContext()), Instruction::Br, - OperandTraits<BranchInst>::op_end(this) - 1, - 1, InsertAtEnd) { + : Instruction(Type::getVoidTy(IfTrue->getContext()), Instruction::Br, + OperandTraits<BranchInst>::op_end(this) - 1, 1, InsertAtEnd) { assert(IfTrue && "Branch destination may not be null!"); Op<-1>() = IfTrue; } BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, - BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(IfTrue->getContext()), Instruction::Br, - OperandTraits<BranchInst>::op_end(this) - 3, - 3, InsertAtEnd) { + BasicBlock *InsertAtEnd) + : Instruction(Type::getVoidTy(IfTrue->getContext()), Instruction::Br, + OperandTraits<BranchInst>::op_end(this) - 3, 3, InsertAtEnd) { Op<-1>() = IfTrue; Op<-2>() = IfFalse; Op<-3>() = Cond; @@ -974,10 +1023,10 @@ BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, #endif } -BranchInst::BranchInst(const BranchInst &BI) : - TerminatorInst(Type::getVoidTy(BI.getContext()), Instruction::Br, - OperandTraits<BranchInst>::op_end(this) - BI.getNumOperands(), - BI.getNumOperands()) { +BranchInst::BranchInst(const BranchInst &BI) + : Instruction(Type::getVoidTy(BI.getContext()), Instruction::Br, + OperandTraits<BranchInst>::op_end(this) - BI.getNumOperands(), + BI.getNumOperands()) { Op<-1>() = BI.Op<-1>(); if (BI.getNumOperands() != 1) { assert(BI.getNumOperands() == 3 && "BR can have 1 or 3 operands!"); @@ -1089,28 +1138,30 @@ void LoadInst::AssertOK() { "Alignment required for atomic load"); } -LoadInst::LoadInst(Value *Ptr, const Twine &Name, Instruction *InsertBef) - : LoadInst(Ptr, Name, /*isVolatile=*/false, InsertBef) {} +LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, + Instruction *InsertBef) + : LoadInst(Ty, Ptr, Name, /*isVolatile=*/false, InsertBef) {} -LoadInst::LoadInst(Value *Ptr, const Twine &Name, BasicBlock *InsertAE) - : LoadInst(Ptr, Name, /*isVolatile=*/false, InsertAE) {} +LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, + BasicBlock *InsertAE) + : LoadInst(Ty, Ptr, Name, /*isVolatile=*/false, InsertAE) {} LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile, Instruction *InsertBef) : LoadInst(Ty, Ptr, Name, isVolatile, /*Align=*/0, InsertBef) {} -LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, +LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile, BasicBlock *InsertAE) - : LoadInst(Ptr, Name, isVolatile, /*Align=*/0, InsertAE) {} + : LoadInst(Ty, Ptr, Name, isVolatile, /*Align=*/0, InsertAE) {} LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile, unsigned Align, Instruction *InsertBef) : LoadInst(Ty, Ptr, Name, isVolatile, Align, AtomicOrdering::NotAtomic, SyncScope::System, InsertBef) {} -LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, +LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile, unsigned Align, BasicBlock *InsertAE) - : LoadInst(Ptr, Name, isVolatile, Align, AtomicOrdering::NotAtomic, + : LoadInst(Ty, Ptr, Name, isVolatile, Align, AtomicOrdering::NotAtomic, SyncScope::System, InsertAE) {} LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile, @@ -1125,12 +1176,11 @@ LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile, setName(Name); } -LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, - unsigned Align, AtomicOrdering Order, - SyncScope::ID SSID, +LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile, + unsigned Align, AtomicOrdering Order, SyncScope::ID SSID, BasicBlock *InsertAE) - : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertAE) { + : UnaryInstruction(Ty, Load, Ptr, InsertAE) { + assert(Ty == cast<PointerType>(Ptr->getType())->getElementType()); setVolatile(isVolatile); setAlignment(Align); setAtomic(Order, SSID); @@ -1138,48 +1188,6 @@ LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, setName(Name); } -LoadInst::LoadInst(Value *Ptr, const char *Name, Instruction *InsertBef) - : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertBef) { - setVolatile(false); - setAlignment(0); - setAtomic(AtomicOrdering::NotAtomic); - AssertOK(); - if (Name && Name[0]) setName(Name); -} - -LoadInst::LoadInst(Value *Ptr, const char *Name, BasicBlock *InsertAE) - : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertAE) { - setVolatile(false); - setAlignment(0); - setAtomic(AtomicOrdering::NotAtomic); - AssertOK(); - if (Name && Name[0]) setName(Name); -} - -LoadInst::LoadInst(Type *Ty, Value *Ptr, const char *Name, bool isVolatile, - Instruction *InsertBef) - : UnaryInstruction(Ty, Load, Ptr, InsertBef) { - assert(Ty == cast<PointerType>(Ptr->getType())->getElementType()); - setVolatile(isVolatile); - setAlignment(0); - setAtomic(AtomicOrdering::NotAtomic); - AssertOK(); - if (Name && Name[0]) setName(Name); -} - -LoadInst::LoadInst(Value *Ptr, const char *Name, bool isVolatile, - BasicBlock *InsertAE) - : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(), - Load, Ptr, InsertAE) { - setVolatile(isVolatile); - setAlignment(0); - setAtomic(AtomicOrdering::NotAtomic); - AssertOK(); - if (Name && Name[0]) setName(Name); -} - void LoadInst::setAlignment(unsigned Align) { assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); assert(Align <= MaximumAlignment && @@ -1376,6 +1384,37 @@ AtomicRMWInst::AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val, Init(Operation, Ptr, Val, Ordering, SSID); } +StringRef AtomicRMWInst::getOperationName(BinOp Op) { + switch (Op) { + case AtomicRMWInst::Xchg: + return "xchg"; + case AtomicRMWInst::Add: + return "add"; + case AtomicRMWInst::Sub: + return "sub"; + case AtomicRMWInst::And: + return "and"; + case AtomicRMWInst::Nand: + return "nand"; + case AtomicRMWInst::Or: + return "or"; + case AtomicRMWInst::Xor: + return "xor"; + case AtomicRMWInst::Max: + return "max"; + case AtomicRMWInst::Min: + return "min"; + case AtomicRMWInst::UMax: + return "umax"; + case AtomicRMWInst::UMin: + return "umin"; + case AtomicRMWInst::BAD_BINOP: + return "<invalid operation>"; + } + + llvm_unreachable("invalid atomicrmw operation"); +} + //===----------------------------------------------------------------------===// // FenceInst Implementation //===----------------------------------------------------------------------===// @@ -1405,7 +1444,7 @@ void GetElementPtrInst::init(Value *Ptr, ArrayRef<Value *> IdxList, assert(getNumOperands() == 1 + IdxList.size() && "NumOperands not initialized?"); Op<0>() = Ptr; - std::copy(IdxList.begin(), IdxList.end(), op_begin() + 1); + llvm::copy(IdxList, op_begin() + 1); setName(Name); } @@ -1700,17 +1739,17 @@ void ShuffleVectorInst::getShuffleMask(const Constant *Mask, } } -bool ShuffleVectorInst::isSingleSourceMask(ArrayRef<int> Mask) { +static bool isSingleSourceMaskImpl(ArrayRef<int> Mask, int NumOpElts) { assert(!Mask.empty() && "Shuffle mask must contain elements"); bool UsesLHS = false; bool UsesRHS = false; - for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) { + for (int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) { if (Mask[i] == -1) continue; - assert(Mask[i] >= 0 && Mask[i] < (NumElts * 2) && + assert(Mask[i] >= 0 && Mask[i] < (NumOpElts * 2) && "Out-of-bounds shuffle mask element"); - UsesLHS |= (Mask[i] < NumElts); - UsesRHS |= (Mask[i] >= NumElts); + UsesLHS |= (Mask[i] < NumOpElts); + UsesRHS |= (Mask[i] >= NumOpElts); if (UsesLHS && UsesRHS) return false; } @@ -1718,18 +1757,30 @@ bool ShuffleVectorInst::isSingleSourceMask(ArrayRef<int> Mask) { return true; } -bool ShuffleVectorInst::isIdentityMask(ArrayRef<int> Mask) { - if (!isSingleSourceMask(Mask)) +bool ShuffleVectorInst::isSingleSourceMask(ArrayRef<int> Mask) { + // We don't have vector operand size information, so assume operands are the + // same size as the mask. + return isSingleSourceMaskImpl(Mask, Mask.size()); +} + +static bool isIdentityMaskImpl(ArrayRef<int> Mask, int NumOpElts) { + if (!isSingleSourceMaskImpl(Mask, NumOpElts)) return false; - for (int i = 0, NumElts = Mask.size(); i < NumElts; ++i) { + for (int i = 0, NumMaskElts = Mask.size(); i < NumMaskElts; ++i) { if (Mask[i] == -1) continue; - if (Mask[i] != i && Mask[i] != (NumElts + i)) + if (Mask[i] != i && Mask[i] != (NumOpElts + i)) return false; } return true; } +bool ShuffleVectorInst::isIdentityMask(ArrayRef<int> Mask) { + // We don't have vector operand size information, so assume operands are the + // same size as the mask. + return isIdentityMaskImpl(Mask, Mask.size()); +} + bool ShuffleVectorInst::isReverseMask(ArrayRef<int> Mask) { if (!isSingleSourceMask(Mask)) return false; @@ -1801,6 +1852,79 @@ bool ShuffleVectorInst::isTransposeMask(ArrayRef<int> Mask) { return true; } +bool ShuffleVectorInst::isExtractSubvectorMask(ArrayRef<int> Mask, + int NumSrcElts, int &Index) { + // Must extract from a single source. + if (!isSingleSourceMaskImpl(Mask, NumSrcElts)) + return false; + + // Must be smaller (else this is an Identity shuffle). + if (NumSrcElts <= (int)Mask.size()) + return false; + + // Find start of extraction, accounting that we may start with an UNDEF. + int SubIndex = -1; + for (int i = 0, e = Mask.size(); i != e; ++i) { + int M = Mask[i]; + if (M < 0) + continue; + int Offset = (M % NumSrcElts) - i; + if (0 <= SubIndex && SubIndex != Offset) + return false; + SubIndex = Offset; + } + + if (0 <= SubIndex) { + Index = SubIndex; + return true; + } + return false; +} + +bool ShuffleVectorInst::isIdentityWithPadding() const { + int NumOpElts = Op<0>()->getType()->getVectorNumElements(); + int NumMaskElts = getType()->getVectorNumElements(); + if (NumMaskElts <= NumOpElts) + return false; + + // The first part of the mask must choose elements from exactly 1 source op. + SmallVector<int, 16> Mask = getShuffleMask(); + if (!isIdentityMaskImpl(Mask, NumOpElts)) + return false; + + // All extending must be with undef elements. + for (int i = NumOpElts; i < NumMaskElts; ++i) + if (Mask[i] != -1) + return false; + + return true; +} + +bool ShuffleVectorInst::isIdentityWithExtract() const { + int NumOpElts = Op<0>()->getType()->getVectorNumElements(); + int NumMaskElts = getType()->getVectorNumElements(); + if (NumMaskElts >= NumOpElts) + return false; + + return isIdentityMaskImpl(getShuffleMask(), NumOpElts); +} + +bool ShuffleVectorInst::isConcat() const { + // Vector concatenation is differentiated from identity with padding. + if (isa<UndefValue>(Op<0>()) || isa<UndefValue>(Op<1>())) + return false; + + int NumOpElts = Op<0>()->getType()->getVectorNumElements(); + int NumMaskElts = getType()->getVectorNumElements(); + if (NumMaskElts != NumOpElts * 2) + return false; + + // Use the mask length rather than the operands' vector lengths here. We + // already know that the shuffle returns a vector twice as long as the inputs, + // and neither of the inputs are undef vectors. If the mask picks consecutive + // elements from both inputs, then this is a concatenation of the inputs. + return isIdentityMaskImpl(getShuffleMask(), NumMaskElts); +} //===----------------------------------------------------------------------===// // InsertValueInst Class @@ -1887,6 +2011,59 @@ Type *ExtractValueInst::getIndexedType(Type *Agg, } //===----------------------------------------------------------------------===// +// UnaryOperator Class +//===----------------------------------------------------------------------===// + +UnaryOperator::UnaryOperator(UnaryOps iType, Value *S, + Type *Ty, const Twine &Name, + Instruction *InsertBefore) + : UnaryInstruction(Ty, iType, S, InsertBefore) { + Op<0>() = S; + setName(Name); + AssertOK(); +} + +UnaryOperator::UnaryOperator(UnaryOps iType, Value *S, + Type *Ty, const Twine &Name, + BasicBlock *InsertAtEnd) + : UnaryInstruction(Ty, iType, S, InsertAtEnd) { + Op<0>() = S; + setName(Name); + AssertOK(); +} + +UnaryOperator *UnaryOperator::Create(UnaryOps Op, Value *S, + const Twine &Name, + Instruction *InsertBefore) { + return new UnaryOperator(Op, S, S->getType(), Name, InsertBefore); +} + +UnaryOperator *UnaryOperator::Create(UnaryOps Op, Value *S, + const Twine &Name, + BasicBlock *InsertAtEnd) { + UnaryOperator *Res = Create(Op, S, Name); + InsertAtEnd->getInstList().push_back(Res); + return Res; +} + +void UnaryOperator::AssertOK() { + Value *LHS = getOperand(0); + (void)LHS; // Silence warnings. +#ifndef NDEBUG + switch (getOpcode()) { + case FNeg: + assert(getType() == LHS->getType() && + "Unary operation should return same type as operand!"); + assert(getType()->isFPOrFPVectorTy() && + "Tried to create a floating-point operation on a " + "non-floating-point type!"); + break; + default: llvm_unreachable("Invalid opcode provided"); + } +#endif +} + +//===----------------------------------------------------------------------===// // BinaryOperator Class //===----------------------------------------------------------------------===// @@ -2068,71 +2245,6 @@ BinaryOperator *BinaryOperator::CreateNot(Value *Op, const Twine &Name, Op->getType(), Name, InsertAtEnd); } -// isConstantAllOnes - Helper function for several functions below -static inline bool isConstantAllOnes(const Value *V) { - if (const Constant *C = dyn_cast<Constant>(V)) - return C->isAllOnesValue(); - return false; -} - -bool BinaryOperator::isNeg(const Value *V) { - if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V)) - if (Bop->getOpcode() == Instruction::Sub) - if (Constant *C = dyn_cast<Constant>(Bop->getOperand(0))) - return C->isNegativeZeroValue(); - return false; -} - -bool BinaryOperator::isFNeg(const Value *V, bool IgnoreZeroSign) { - if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V)) - if (Bop->getOpcode() == Instruction::FSub) - if (Constant *C = dyn_cast<Constant>(Bop->getOperand(0))) { - if (!IgnoreZeroSign) - IgnoreZeroSign = cast<Instruction>(V)->hasNoSignedZeros(); - return !IgnoreZeroSign ? C->isNegativeZeroValue() : C->isZeroValue(); - } - return false; -} - -bool BinaryOperator::isNot(const Value *V) { - if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V)) - return (Bop->getOpcode() == Instruction::Xor && - (isConstantAllOnes(Bop->getOperand(1)) || - isConstantAllOnes(Bop->getOperand(0)))); - return false; -} - -Value *BinaryOperator::getNegArgument(Value *BinOp) { - return cast<BinaryOperator>(BinOp)->getOperand(1); -} - -const Value *BinaryOperator::getNegArgument(const Value *BinOp) { - return getNegArgument(const_cast<Value*>(BinOp)); -} - -Value *BinaryOperator::getFNegArgument(Value *BinOp) { - return cast<BinaryOperator>(BinOp)->getOperand(1); -} - -const Value *BinaryOperator::getFNegArgument(const Value *BinOp) { - return getFNegArgument(const_cast<Value*>(BinOp)); -} - -Value *BinaryOperator::getNotArgument(Value *BinOp) { - assert(isNot(BinOp) && "getNotArgument on non-'not' instruction!"); - BinaryOperator *BO = cast<BinaryOperator>(BinOp); - Value *Op0 = BO->getOperand(0); - Value *Op1 = BO->getOperand(1); - if (isConstantAllOnes(Op0)) return Op1; - - assert(isConstantAllOnes(Op1)); - return Op0; -} - -const Value *BinaryOperator::getNotArgument(const Value *BinOp) { - return getNotArgument(const_cast<Value*>(BinOp)); -} - // Exchange the two operands to this instruction. This instruction is safe to // use on any binary instruction and does not modify the semantics of the // instruction. If the instruction is order-dependent (SetLT f.e.), the opcode @@ -2978,12 +3090,14 @@ CastInst::castIsValid(Instruction::CastOps op, Value *S, Type *DstTy) { return false; // A vector of pointers must have the same number of elements. - if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy)) { - if (VectorType *DstVecTy = dyn_cast<VectorType>(DstTy)) - return (SrcVecTy->getNumElements() == DstVecTy->getNumElements()); - - return false; - } + VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy); + VectorType *DstVecTy = dyn_cast<VectorType>(DstTy); + if (SrcVecTy && DstVecTy) + return (SrcVecTy->getNumElements() == DstVecTy->getNumElements()); + if (SrcVecTy) + return SrcVecTy->getNumElements() == 1; + if (DstVecTy) + return DstVecTy->getNumElements() == 1; return true; } @@ -3171,15 +3285,18 @@ AddrSpaceCastInst::AddrSpaceCastInst( //===----------------------------------------------------------------------===// CmpInst::CmpInst(Type *ty, OtherOps op, Predicate predicate, Value *LHS, - Value *RHS, const Twine &Name, Instruction *InsertBefore) + Value *RHS, const Twine &Name, Instruction *InsertBefore, + Instruction *FlagsSource) : Instruction(ty, op, OperandTraits<CmpInst>::op_begin(this), OperandTraits<CmpInst>::operands(this), InsertBefore) { - Op<0>() = LHS; - Op<1>() = RHS; + Op<0>() = LHS; + Op<1>() = RHS; setPredicate((Predicate)predicate); setName(Name); + if (FlagsSource) + copyIRFlags(FlagsSource); } CmpInst::CmpInst(Type *ty, OtherOps op, Predicate predicate, Value *LHS, @@ -3518,8 +3635,8 @@ void SwitchInst::init(Value *Value, BasicBlock *Default, unsigned NumReserved) { /// constructor can also autoinsert before another instruction. SwitchInst::SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, Instruction *InsertBefore) - : TerminatorInst(Type::getVoidTy(Value->getContext()), Instruction::Switch, - nullptr, 0, InsertBefore) { + : Instruction(Type::getVoidTy(Value->getContext()), Instruction::Switch, + nullptr, 0, InsertBefore) { init(Value, Default, 2+NumCases*2); } @@ -3529,13 +3646,13 @@ SwitchInst::SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, /// constructor also autoinserts at the end of the specified BasicBlock. SwitchInst::SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, BasicBlock *InsertAtEnd) - : TerminatorInst(Type::getVoidTy(Value->getContext()), Instruction::Switch, - nullptr, 0, InsertAtEnd) { + : Instruction(Type::getVoidTy(Value->getContext()), Instruction::Switch, + nullptr, 0, InsertAtEnd) { init(Value, Default, 2+NumCases*2); } SwitchInst::SwitchInst(const SwitchInst &SI) - : TerminatorInst(SI.getType(), Instruction::Switch, nullptr, 0) { + : Instruction(SI.getType(), Instruction::Switch, nullptr, 0) { init(SI.getCondition(), SI.getDefaultDest(), SI.getNumOperands()); setNumHungOffUseOperands(SI.getNumOperands()); Use *OL = getOperandList(); @@ -3547,7 +3664,6 @@ SwitchInst::SwitchInst(const SwitchInst &SI) SubclassOptionalData = SI.SubclassOptionalData; } - /// addCase - Add an entry to the switch instruction... /// void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) { @@ -3626,21 +3742,21 @@ void IndirectBrInst::growOperands() { IndirectBrInst::IndirectBrInst(Value *Address, unsigned NumCases, Instruction *InsertBefore) -: TerminatorInst(Type::getVoidTy(Address->getContext()),Instruction::IndirectBr, - nullptr, 0, InsertBefore) { + : Instruction(Type::getVoidTy(Address->getContext()), + Instruction::IndirectBr, nullptr, 0, InsertBefore) { init(Address, NumCases); } IndirectBrInst::IndirectBrInst(Value *Address, unsigned NumCases, BasicBlock *InsertAtEnd) -: TerminatorInst(Type::getVoidTy(Address->getContext()),Instruction::IndirectBr, - nullptr, 0, InsertAtEnd) { + : Instruction(Type::getVoidTy(Address->getContext()), + Instruction::IndirectBr, nullptr, 0, InsertAtEnd) { init(Address, NumCases); } IndirectBrInst::IndirectBrInst(const IndirectBrInst &IBI) - : TerminatorInst(Type::getVoidTy(IBI.getContext()), Instruction::IndirectBr, - nullptr, IBI.getNumOperands()) { + : Instruction(Type::getVoidTy(IBI.getContext()), Instruction::IndirectBr, + nullptr, IBI.getNumOperands()) { allocHungoffUses(IBI.getNumOperands()); Use *OL = getOperandList(); const Use *InOL = IBI.getOperandList(); @@ -3688,6 +3804,10 @@ GetElementPtrInst *GetElementPtrInst::cloneImpl() const { return new (getNumOperands()) GetElementPtrInst(*this); } +UnaryOperator *UnaryOperator::cloneImpl() const { + return Create(getOpcode(), Op<0>()); +} + BinaryOperator *BinaryOperator::cloneImpl() const { return Create(getOpcode(), Op<0>(), Op<1>()); } @@ -3718,7 +3838,7 @@ AllocaInst *AllocaInst::cloneImpl() const { } LoadInst *LoadInst::cloneImpl() const { - return new LoadInst(getOperand(0), Twine(), isVolatile(), + return new LoadInst(getType(), getOperand(0), Twine(), isVolatile(), getAlignment(), getOrdering(), getSyncScopeID()); } |
