1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00
llvm-mirror/lib/IR/Instructions.cpp
Konstantin Zhuravlyov d382d6f3fc Enhance synchscope representation
OpenCL 2.0 introduces the notion of memory scopes in atomic operations to
  global and local memory. These scopes restrict how synchronization is
  achieved, which can result in improved performance.

  This change extends existing notion of synchronization scopes in LLVM to
  support arbitrary scopes expressed as target-specific strings, in addition to
  the already defined scopes (single thread, system).

  The LLVM IR and MIR syntax for expressing synchronization scopes has changed
  to use *syncscope("<scope>")*, where <scope> can be "singlethread" (this
  replaces *singlethread* keyword), or a target-specific name. As before, if
  the scope is not specified, it defaults to CrossThread/System scope.

  Implementation details:
    - Mapping from synchronization scope name/string to synchronization scope id
      is stored in LLVM context;
    - CrossThread/System and SingleThread scopes are pre-defined to efficiently
      check for known scopes without comparing strings;
    - Synchronization scope names are stored in SYNC_SCOPE_NAMES_BLOCK in
      the bitcode.

Differential Revision: https://reviews.llvm.org/D21723

llvm-svn: 307722
2017-07-11 22:23:00 +00:00

3959 lines
150 KiB
C++

//===- Instructions.cpp - Implement the LLVM instructions -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements all of the non-inline methods for the LLVM instruction
// classes.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/Instructions.h"
#include "LLVMContextImpl.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/AtomicOrdering.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <vector>
using namespace llvm;
//===----------------------------------------------------------------------===//
// CallSite Class
//===----------------------------------------------------------------------===//
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");
}
//===----------------------------------------------------------------------===//
// SelectInst Class
//===----------------------------------------------------------------------===//
/// areInvalidOperands - Return a string if the specified operands are invalid
/// for a select operation, otherwise return null.
const char *SelectInst::areInvalidOperands(Value *Op0, Value *Op1, Value *Op2) {
if (Op1->getType() != Op2->getType())
return "both values to select must have same type";
if (Op1->getType()->isTokenTy())
return "select values cannot have token type";
if (VectorType *VT = dyn_cast<VectorType>(Op0->getType())) {
// Vector select.
if (VT->getElementType() != Type::getInt1Ty(Op0->getContext()))
return "vector select condition element type must be i1";
VectorType *ET = dyn_cast<VectorType>(Op1->getType());
if (!ET)
return "selected values for vector select must be vectors";
if (ET->getNumElements() != VT->getNumElements())
return "vector select requires selected vectors to have "
"the same vector length as select condition";
} else if (Op0->getType() != Type::getInt1Ty(Op0->getContext())) {
return "select condition must be i1 or <n x i1>";
}
return nullptr;
}
//===----------------------------------------------------------------------===//
// PHINode Class
//===----------------------------------------------------------------------===//
PHINode::PHINode(const PHINode &PN)
: Instruction(PN.getType(), Instruction::PHI, nullptr, PN.getNumOperands()),
ReservedSpace(PN.getNumOperands()) {
allocHungoffUses(PN.getNumOperands());
std::copy(PN.op_begin(), PN.op_end(), op_begin());
std::copy(PN.block_begin(), PN.block_end(), block_begin());
SubclassOptionalData = PN.SubclassOptionalData;
}
// removeIncomingValue - Remove an incoming value. This is useful if a
// predecessor basic block is deleted.
Value *PHINode::removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty) {
Value *Removed = getIncomingValue(Idx);
// Move everything after this operand down.
//
// FIXME: we could just swap with the end of the list, then erase. However,
// clients might not expect this to happen. The code as it is thrashes the
// use/def lists, which is kinda lame.
std::copy(op_begin() + Idx + 1, op_end(), op_begin() + Idx);
std::copy(block_begin() + Idx + 1, block_end(), block_begin() + Idx);
// Nuke the last value.
Op<-1>().set(nullptr);
setNumHungOffUseOperands(getNumOperands() - 1);
// If the PHI node is dead, because it has zero entries, nuke it now.
if (getNumOperands() == 0 && DeletePHIIfEmpty) {
// If anyone is using this PHI, make them use a dummy value instead...
replaceAllUsesWith(UndefValue::get(getType()));
eraseFromParent();
}
return Removed;
}
/// growOperands - grow operands - This grows the operand list in response
/// to a push_back style of operation. This grows the number of ops by 1.5
/// times.
///
void PHINode::growOperands() {
unsigned e = getNumOperands();
unsigned NumOps = e + e / 2;
if (NumOps < 2) NumOps = 2; // 2 op PHI nodes are VERY common.
ReservedSpace = NumOps;
growHungoffUses(ReservedSpace, /* IsPhi */ true);
}
/// hasConstantValue - If the specified PHI node always merges together the same
/// value, return the value, otherwise return null.
Value *PHINode::hasConstantValue() const {
// Exploit the fact that phi nodes always have at least one entry.
Value *ConstantValue = getIncomingValue(0);
for (unsigned i = 1, e = getNumIncomingValues(); i != e; ++i)
if (getIncomingValue(i) != ConstantValue && getIncomingValue(i) != this) {
if (ConstantValue != this)
return nullptr; // Incoming values not all the same.
// The case where the first value is this PHI.
ConstantValue = getIncomingValue(i);
}
if (ConstantValue == this)
return UndefValue::get(getType());
return ConstantValue;
}
/// hasConstantOrUndefValue - Whether the specified PHI node always merges
/// together the same value, assuming that undefs result in the same value as
/// non-undefs.
/// Unlike \ref hasConstantValue, this does not return a value because the
/// unique non-undef incoming value need not dominate the PHI node.
bool PHINode::hasConstantOrUndefValue() const {
Value *ConstantValue = nullptr;
for (unsigned i = 0, e = getNumIncomingValues(); i != e; ++i) {
Value *Incoming = getIncomingValue(i);
if (Incoming != this && !isa<UndefValue>(Incoming)) {
if (ConstantValue && ConstantValue != Incoming)
return false;
ConstantValue = Incoming;
}
}
return true;
}
//===----------------------------------------------------------------------===//
// LandingPadInst Implementation
//===----------------------------------------------------------------------===//
LandingPadInst::LandingPadInst(Type *RetTy, unsigned NumReservedValues,
const Twine &NameStr, Instruction *InsertBefore)
: Instruction(RetTy, Instruction::LandingPad, nullptr, 0, InsertBefore) {
init(NumReservedValues, NameStr);
}
LandingPadInst::LandingPadInst(Type *RetTy, unsigned NumReservedValues,
const Twine &NameStr, BasicBlock *InsertAtEnd)
: Instruction(RetTy, Instruction::LandingPad, nullptr, 0, InsertAtEnd) {
init(NumReservedValues, NameStr);
}
LandingPadInst::LandingPadInst(const LandingPadInst &LP)
: Instruction(LP.getType(), Instruction::LandingPad, nullptr,
LP.getNumOperands()),
ReservedSpace(LP.getNumOperands()) {
allocHungoffUses(LP.getNumOperands());
Use *OL = getOperandList();
const Use *InOL = LP.getOperandList();
for (unsigned I = 0, E = ReservedSpace; I != E; ++I)
OL[I] = InOL[I];
setCleanup(LP.isCleanup());
}
LandingPadInst *LandingPadInst::Create(Type *RetTy, unsigned NumReservedClauses,
const Twine &NameStr,
Instruction *InsertBefore) {
return new LandingPadInst(RetTy, NumReservedClauses, NameStr, InsertBefore);
}
LandingPadInst *LandingPadInst::Create(Type *RetTy, unsigned NumReservedClauses,
const Twine &NameStr,
BasicBlock *InsertAtEnd) {
return new LandingPadInst(RetTy, NumReservedClauses, NameStr, InsertAtEnd);
}
void LandingPadInst::init(unsigned NumReservedValues, const Twine &NameStr) {
ReservedSpace = NumReservedValues;
setNumHungOffUseOperands(0);
allocHungoffUses(ReservedSpace);
setName(NameStr);
setCleanup(false);
}
/// growOperands - grow operands - This grows the operand list in response to a
/// push_back style of operation. This grows the number of ops by 2 times.
void LandingPadInst::growOperands(unsigned Size) {
unsigned e = getNumOperands();
if (ReservedSpace >= e + Size) return;
ReservedSpace = (std::max(e, 1U) + Size / 2) * 2;
growHungoffUses(ReservedSpace);
}
void LandingPadInst::addClause(Constant *Val) {
unsigned OpNo = getNumOperands();
growOperands(1);
assert(OpNo < ReservedSpace && "Growing didn't work!");
setNumHungOffUseOperands(getNumOperands() + 1);
getOperandList()[OpNo] = Val;
}
//===----------------------------------------------------------------------===//
// CallInst Implementation
//===----------------------------------------------------------------------===//
void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr) {
this->FTy = FTy;
assert(getNumOperands() == Args.size() + CountBundleInputs(Bundles) + 1 &&
"NumOperands not set up?");
Op<-1>() = Func;
#ifndef NDEBUG
assert((Args.size() == FTy->getNumParams() ||
(FTy->isVarArg() && Args.size() > FTy->getNumParams())) &&
"Calling a function with bad signature!");
for (unsigned i = 0; i != Args.size(); ++i)
assert((i >= FTy->getNumParams() ||
FTy->getParamType(i) == Args[i]->getType()) &&
"Calling a function with a bad signature!");
#endif
std::copy(Args.begin(), Args.end(), op_begin());
auto It = populateBundleOperandInfos(Bundles, Args.size());
(void)It;
assert(It + 1 == op_end() && "Should add up!");
setName(NameStr);
}
void CallInst::init(Value *Func, const Twine &NameStr) {
FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
assert(getNumOperands() == 1 && "NumOperands not set up?");
Op<-1>() = Func;
assert(FTy->getNumParams() == 0 && "Calling a function with bad signature");
setName(NameStr);
}
CallInst::CallInst(Value *Func, const Twine &Name,
Instruction *InsertBefore)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
->getElementType())->getReturnType(),
Instruction::Call,
OperandTraits<CallInst>::op_end(this) - 1,
1, InsertBefore) {
init(Func, Name);
}
CallInst::CallInst(Value *Func, const Twine &Name,
BasicBlock *InsertAtEnd)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
->getElementType())->getReturnType(),
Instruction::Call,
OperandTraits<CallInst>::op_end(this) - 1,
1, InsertAtEnd) {
init(Func, Name);
}
CallInst::CallInst(const CallInst &CI)
: Instruction(CI.getType(), Instruction::Call,
OperandTraits<CallInst>::op_end(this) - CI.getNumOperands(),
CI.getNumOperands()),
Attrs(CI.Attrs), FTy(CI.FTy) {
setTailCallKind(CI.getTailCallKind());
setCallingConv(CI.getCallingConv());
std::copy(CI.op_begin(), CI.op_end(), op_begin());
std::copy(CI.bundle_op_info_begin(), CI.bundle_op_info_end(),
bundle_op_info_begin());
SubclassOptionalData = CI.SubclassOptionalData;
}
CallInst *CallInst::Create(CallInst *CI, ArrayRef<OperandBundleDef> OpB,
Instruction *InsertPt) {
std::vector<Value *> Args(CI->arg_begin(), CI->arg_end());
auto *NewCI = CallInst::Create(CI->getCalledValue(), Args, OpB, CI->getName(),
InsertPt);
NewCI->setTailCallKind(CI->getTailCallKind());
NewCI->setCallingConv(CI->getCallingConv());
NewCI->SubclassOptionalData = CI->SubclassOptionalData;
NewCI->setAttributes(CI->getAttributes());
NewCI->setDebugLoc(CI->getDebugLoc());
return NewCI;
}
Value *CallInst::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;
}
void CallInst::addAttribute(unsigned i, Attribute::AttrKind Kind) {
AttributeList PAL = getAttributes();
PAL = PAL.addAttribute(getContext(), i, Kind);
setAttributes(PAL);
}
void CallInst::addAttribute(unsigned i, Attribute Attr) {
AttributeList PAL = getAttributes();
PAL = PAL.addAttribute(getContext(), i, Attr);
setAttributes(PAL);
}
void CallInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
assert(ArgNo < getNumArgOperands() && "Out of bounds");
AttributeList PAL = getAttributes();
PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind);
setAttributes(PAL);
}
void CallInst::addParamAttr(unsigned ArgNo, Attribute Attr) {
assert(ArgNo < getNumArgOperands() && "Out of bounds");
AttributeList PAL = getAttributes();
PAL = PAL.addParamAttribute(getContext(), ArgNo, Attr);
setAttributes(PAL);
}
void CallInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) {
AttributeList PAL = getAttributes();
PAL = PAL.removeAttribute(getContext(), i, Kind);
setAttributes(PAL);
}
void CallInst::removeAttribute(unsigned i, StringRef Kind) {
AttributeList PAL = getAttributes();
PAL = PAL.removeAttribute(getContext(), i, Kind);
setAttributes(PAL);
}
void CallInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
assert(ArgNo < getNumArgOperands() && "Out of bounds");
AttributeList PAL = getAttributes();
PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
setAttributes(PAL);
}
void CallInst::removeParamAttr(unsigned ArgNo, StringRef Kind) {
assert(ArgNo < getNumArgOperands() && "Out of bounds");
AttributeList PAL = getAttributes();
PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
setAttributes(PAL);
}
void CallInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) {
AttributeList PAL = getAttributes();
PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes);
setAttributes(PAL);
}
void CallInst::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) {
AttributeList PAL = getAttributes();
PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes);
setAttributes(PAL);
}
bool CallInst::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;
}
bool CallInst::paramHasAttr(unsigned i, Attribute::AttrKind Kind) const {
assert(i < getNumArgOperands() && "Param index out of bounds!");
if (Attrs.hasParamAttribute(i, Kind))
return true;
if (const Function *F = getCalledFunction())
return F->getAttributes().hasParamAttribute(i, Kind);
return false;
}
bool CallInst::dataOperandHasImpliedAttr(unsigned i,
Attribute::AttrKind Kind) const {
// There are getNumOperands() - 1 data operands. The last operand is the
// callee.
assert(i < getNumOperands() && "Data operand index out of bounds!");
// The attribute A can either be directly specified, if the operand in
// question is a call argument; or be indirectly implied by the kind of its
// containing operand bundle, if the operand is a bundle operand.
if (i == AttributeList::ReturnIndex)
return hasRetAttr(Kind);
// FIXME: Avoid these i - 1 calculations and update the API to use zero-based
// indices.
if (i < (getNumArgOperands() + 1))
return paramHasAttr(i - 1, Kind);
assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) &&
"Must be either a call argument or an operand bundle!");
return bundleOperandHasAttr(i - 1, Kind);
}
/// IsConstantOne - Return true only if val is constant int 1
static bool IsConstantOne(Value *val) {
assert(val && "IsConstantOne does not work with nullptr val");
const ConstantInt *CVal = dyn_cast<ConstantInt>(val);
return CVal && CVal->isOne();
}
static Instruction *createMalloc(Instruction *InsertBefore,
BasicBlock *InsertAtEnd, Type *IntPtrTy,
Type *AllocTy, Value *AllocSize,
Value *ArraySize,
ArrayRef<OperandBundleDef> OpB,
Function *MallocF, const Twine &Name) {
assert(((!InsertBefore && InsertAtEnd) || (InsertBefore && !InsertAtEnd)) &&
"createMalloc needs either InsertBefore or InsertAtEnd");
// malloc(type) becomes:
// bitcast (i8* malloc(typeSize)) to type*
// malloc(type, arraySize) becomes:
// bitcast (i8* malloc(typeSize*arraySize)) to type*
if (!ArraySize)
ArraySize = ConstantInt::get(IntPtrTy, 1);
else if (ArraySize->getType() != IntPtrTy) {
if (InsertBefore)
ArraySize = CastInst::CreateIntegerCast(ArraySize, IntPtrTy, false,
"", InsertBefore);
else
ArraySize = CastInst::CreateIntegerCast(ArraySize, IntPtrTy, false,
"", InsertAtEnd);
}
if (!IsConstantOne(ArraySize)) {
if (IsConstantOne(AllocSize)) {
AllocSize = ArraySize; // Operand * 1 = Operand
} else if (Constant *CO = dyn_cast<Constant>(ArraySize)) {
Constant *Scale = ConstantExpr::getIntegerCast(CO, IntPtrTy,
false /*ZExt*/);
// Malloc arg is constant product of type size and array size
AllocSize = ConstantExpr::getMul(Scale, cast<Constant>(AllocSize));
} else {
// Multiply type size by the array size...
if (InsertBefore)
AllocSize = BinaryOperator::CreateMul(ArraySize, AllocSize,
"mallocsize", InsertBefore);
else
AllocSize = BinaryOperator::CreateMul(ArraySize, AllocSize,
"mallocsize", InsertAtEnd);
}
}
assert(AllocSize->getType() == IntPtrTy && "malloc arg is wrong size");
// Create the call to Malloc.
BasicBlock *BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
Module *M = BB->getParent()->getParent();
Type *BPTy = Type::getInt8PtrTy(BB->getContext());
Value *MallocFunc = MallocF;
if (!MallocFunc)
// prototype malloc as "void *malloc(size_t)"
MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy);
PointerType *AllocPtrType = PointerType::getUnqual(AllocTy);
CallInst *MCall = nullptr;
Instruction *Result = nullptr;
if (InsertBefore) {
MCall = CallInst::Create(MallocFunc, AllocSize, OpB, "malloccall",
InsertBefore);
Result = MCall;
if (Result->getType() != AllocPtrType)
// Create a cast instruction to convert to the right type...
Result = new BitCastInst(MCall, AllocPtrType, Name, InsertBefore);
} else {
MCall = CallInst::Create(MallocFunc, AllocSize, OpB, "malloccall");
Result = MCall;
if (Result->getType() != AllocPtrType) {
InsertAtEnd->getInstList().push_back(MCall);
// Create a cast instruction to convert to the right type...
Result = new BitCastInst(MCall, AllocPtrType, Name);
}
}
MCall->setTailCall();
if (Function *F = dyn_cast<Function>(MallocFunc)) {
MCall->setCallingConv(F->getCallingConv());
if (!F->returnDoesNotAlias())
F->setReturnDoesNotAlias();
}
assert(!MCall->getType()->isVoidTy() && "Malloc has void return type");
return Result;
}
/// CreateMalloc - Generate the IR for a call to malloc:
/// 1. Compute the malloc call's argument as the specified type's size,
/// possibly multiplied by the array size if the array size is not
/// constant 1.
/// 2. Call malloc with that argument.
/// 3. Bitcast the result of the malloc call to the specified type.
Instruction *CallInst::CreateMalloc(Instruction *InsertBefore,
Type *IntPtrTy, Type *AllocTy,
Value *AllocSize, Value *ArraySize,
Function *MallocF,
const Twine &Name) {
return createMalloc(InsertBefore, nullptr, IntPtrTy, AllocTy, AllocSize,
ArraySize, None, MallocF, Name);
}
Instruction *CallInst::CreateMalloc(Instruction *InsertBefore,
Type *IntPtrTy, Type *AllocTy,
Value *AllocSize, Value *ArraySize,
ArrayRef<OperandBundleDef> OpB,
Function *MallocF,
const Twine &Name) {
return createMalloc(InsertBefore, nullptr, IntPtrTy, AllocTy, AllocSize,
ArraySize, OpB, MallocF, Name);
}
/// CreateMalloc - Generate the IR for a call to malloc:
/// 1. Compute the malloc call's argument as the specified type's size,
/// possibly multiplied by the array size if the array size is not
/// constant 1.
/// 2. Call malloc with that argument.
/// 3. Bitcast the result of the malloc call to the specified type.
/// Note: This function does not add the bitcast to the basic block, that is the
/// responsibility of the caller.
Instruction *CallInst::CreateMalloc(BasicBlock *InsertAtEnd,
Type *IntPtrTy, Type *AllocTy,
Value *AllocSize, Value *ArraySize,
Function *MallocF, const Twine &Name) {
return createMalloc(nullptr, InsertAtEnd, IntPtrTy, AllocTy, AllocSize,
ArraySize, None, MallocF, Name);
}
Instruction *CallInst::CreateMalloc(BasicBlock *InsertAtEnd,
Type *IntPtrTy, Type *AllocTy,
Value *AllocSize, Value *ArraySize,
ArrayRef<OperandBundleDef> OpB,
Function *MallocF, const Twine &Name) {
return createMalloc(nullptr, InsertAtEnd, IntPtrTy, AllocTy, AllocSize,
ArraySize, OpB, MallocF, Name);
}
static Instruction *createFree(Value *Source,
ArrayRef<OperandBundleDef> Bundles,
Instruction *InsertBefore,
BasicBlock *InsertAtEnd) {
assert(((!InsertBefore && InsertAtEnd) || (InsertBefore && !InsertAtEnd)) &&
"createFree needs either InsertBefore or InsertAtEnd");
assert(Source->getType()->isPointerTy() &&
"Can not free something of nonpointer type!");
BasicBlock *BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
Module *M = BB->getParent()->getParent();
Type *VoidTy = Type::getVoidTy(M->getContext());
Type *IntPtrTy = Type::getInt8PtrTy(M->getContext());
// prototype free as "void free(void*)"
Value *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy);
CallInst *Result = nullptr;
Value *PtrCast = Source;
if (InsertBefore) {
if (Source->getType() != IntPtrTy)
PtrCast = new BitCastInst(Source, IntPtrTy, "", InsertBefore);
Result = CallInst::Create(FreeFunc, PtrCast, Bundles, "", InsertBefore);
} else {
if (Source->getType() != IntPtrTy)
PtrCast = new BitCastInst(Source, IntPtrTy, "", InsertAtEnd);
Result = CallInst::Create(FreeFunc, PtrCast, Bundles, "");
}
Result->setTailCall();
if (Function *F = dyn_cast<Function>(FreeFunc))
Result->setCallingConv(F->getCallingConv());
return Result;
}
/// CreateFree - Generate the IR for a call to the builtin free function.
Instruction *CallInst::CreateFree(Value *Source, Instruction *InsertBefore) {
return createFree(Source, None, InsertBefore, nullptr);
}
Instruction *CallInst::CreateFree(Value *Source,
ArrayRef<OperandBundleDef> Bundles,
Instruction *InsertBefore) {
return createFree(Source, Bundles, InsertBefore, nullptr);
}
/// CreateFree - Generate the IR for a call to the builtin free function.
/// Note: This function does not add the call to the basic block, that is the
/// responsibility of the caller.
Instruction *CallInst::CreateFree(Value *Source, BasicBlock *InsertAtEnd) {
Instruction *FreeCall = createFree(Source, None, nullptr, InsertAtEnd);
assert(FreeCall && "CreateFree did not create a CallInst");
return FreeCall;
}
Instruction *CallInst::CreateFree(Value *Source,
ArrayRef<OperandBundleDef> Bundles,
BasicBlock *InsertAtEnd) {
Instruction *FreeCall = createFree(Source, Bundles, nullptr, InsertAtEnd);
assert(FreeCall && "CreateFree did not create a CallInst");
return FreeCall;
}
//===----------------------------------------------------------------------===//
// InvokeInst Implementation
//===----------------------------------------------------------------------===//
void InvokeInst::init(FunctionType *FTy, Value *Fn, BasicBlock *IfNormal,
BasicBlock *IfException, ArrayRef<Value *> Args,
ArrayRef<OperandBundleDef> Bundles,
const Twine &NameStr) {
this->FTy = FTy;
assert(getNumOperands() == 3 + Args.size() + CountBundleInputs(Bundles) &&
"NumOperands not set up?");
Op<-3>() = Fn;
Op<-2>() = IfNormal;
Op<-1>() = IfException;
#ifndef NDEBUG
assert(((Args.size() == FTy->getNumParams()) ||
(FTy->isVarArg() && Args.size() > FTy->getNumParams())) &&
"Invoking a function with bad signature");
for (unsigned i = 0, e = Args.size(); i != e; i++)
assert((i >= FTy->getNumParams() ||
FTy->getParamType(i) == Args[i]->getType()) &&
"Invoking a function with a bad signature!");
#endif
std::copy(Args.begin(), Args.end(), op_begin());
auto It = populateBundleOperandInfos(Bundles, Args.size());
(void)It;
assert(It + 3 == op_end() && "Should add up!");
setName(NameStr);
}
InvokeInst::InvokeInst(const InvokeInst &II)
: TerminatorInst(II.getType(), Instruction::Invoke,
OperandTraits<InvokeInst>::op_end(this) -
II.getNumOperands(),
II.getNumOperands()),
Attrs(II.Attrs), FTy(II.FTy) {
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(),
bundle_op_info_begin());
SubclassOptionalData = II.SubclassOptionalData;
}
InvokeInst *InvokeInst::Create(InvokeInst *II, ArrayRef<OperandBundleDef> OpB,
Instruction *InsertPt) {
std::vector<Value *> Args(II->arg_begin(), II->arg_end());
auto *NewII = InvokeInst::Create(II->getCalledValue(), II->getNormalDest(),
II->getUnwindDest(), Args, OpB,
II->getName(), InsertPt);
NewII->setCallingConv(II->getCallingConv());
NewII->SubclassOptionalData = II->SubclassOptionalData;
NewII->setAttributes(II->getAttributes());
NewII->setDebugLoc(II->getDebugLoc());
return NewII;
}
Value *InvokeInst::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 InvokeInst::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;
}
bool InvokeInst::paramHasAttr(unsigned i, Attribute::AttrKind Kind) const {
assert(i < getNumArgOperands() && "Param index out of bounds!");
if (Attrs.hasParamAttribute(i, Kind))
return true;
if (const Function *F = getCalledFunction())
return F->getAttributes().hasParamAttribute(i, Kind);
return false;
}
bool InvokeInst::dataOperandHasImpliedAttr(unsigned i,
Attribute::AttrKind Kind) const {
// There are getNumOperands() - 3 data operands. The last three operands are
// the callee and the two successor basic blocks.
assert(i < (getNumOperands() - 2) && "Data operand index out of bounds!");
// The attribute A can either be directly specified, if the operand in
// question is an invoke argument; or be indirectly implied by the kind of its
// containing operand bundle, if the operand is a bundle operand.
if (i == AttributeList::ReturnIndex)
return hasRetAttr(Kind);
// FIXME: Avoid these i - 1 calculations and update the API to use zero-based
// indices.
if (i < (getNumArgOperands() + 1))
return paramHasAttr(i - 1, Kind);
assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) &&
"Must be either an invoke argument or an operand bundle!");
return bundleOperandHasAttr(i - 1, Kind);
}
void InvokeInst::addAttribute(unsigned i, Attribute::AttrKind Kind) {
AttributeList PAL = getAttributes();
PAL = PAL.addAttribute(getContext(), i, Kind);
setAttributes(PAL);
}
void InvokeInst::addAttribute(unsigned i, Attribute Attr) {
AttributeList PAL = getAttributes();
PAL = PAL.addAttribute(getContext(), i, Attr);
setAttributes(PAL);
}
void InvokeInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
AttributeList PAL = getAttributes();
PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind);
setAttributes(PAL);
}
void InvokeInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) {
AttributeList PAL = getAttributes();
PAL = PAL.removeAttribute(getContext(), i, Kind);
setAttributes(PAL);
}
void InvokeInst::removeAttribute(unsigned i, StringRef Kind) {
AttributeList PAL = getAttributes();
PAL = PAL.removeAttribute(getContext(), i, Kind);
setAttributes(PAL);
}
void InvokeInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
AttributeList PAL = getAttributes();
PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
setAttributes(PAL);
}
void InvokeInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) {
AttributeList PAL = getAttributes();
PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes);
setAttributes(PAL);
}
void InvokeInst::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) {
AttributeList PAL = getAttributes();
PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes);
setAttributes(PAL);
}
LandingPadInst *InvokeInst::getLandingPadInst() const {
return cast<LandingPadInst>(getUnwindDest()->getFirstNonPHI());
}
//===----------------------------------------------------------------------===//
// ReturnInst Implementation
//===----------------------------------------------------------------------===//
ReturnInst::ReturnInst(const ReturnInst &RI)
: TerminatorInst(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) {
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) {
if (retVal)
Op<0>() = retVal;
}
ReturnInst::ReturnInst(LLVMContext &Context, BasicBlock *InsertAtEnd)
: TerminatorInst(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) {
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) {
Op<0>() = Exn;
}
ResumeInst::ResumeInst(Value *Exn, BasicBlock *InsertAtEnd)
: TerminatorInst(Type::getVoidTy(Exn->getContext()), Instruction::Resume,
OperandTraits<ResumeInst>::op_begin(this), 1, InsertAtEnd) {
Op<0>() = Exn;
}
//===----------------------------------------------------------------------===//
// CleanupReturnInst Implementation
//===----------------------------------------------------------------------===//
CleanupReturnInst::CleanupReturnInst(const CleanupReturnInst &CRI)
: TerminatorInst(CRI.getType(), Instruction::CleanupRet,
OperandTraits<CleanupReturnInst>::op_end(this) -
CRI.getNumOperands(),
CRI.getNumOperands()) {
setInstructionSubclassData(CRI.getSubclassDataFromInstruction());
Op<0>() = CRI.Op<0>();
if (CRI.hasUnwindDest())
Op<1>() = CRI.Op<1>();
}
void CleanupReturnInst::init(Value *CleanupPad, BasicBlock *UnwindBB) {
if (UnwindBB)
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
Op<0>() = CleanupPad;
if (UnwindBB)
Op<1>() = 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) {
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) {
init(CleanupPad, UnwindBB);
}
//===----------------------------------------------------------------------===//
// CatchReturnInst Implementation
//===----------------------------------------------------------------------===//
void CatchReturnInst::init(Value *CatchPad, BasicBlock *BB) {
Op<0>() = CatchPad;
Op<1>() = BB;
}
CatchReturnInst::CatchReturnInst(const CatchReturnInst &CRI)
: TerminatorInst(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) {
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) {
init(CatchPad, BB);
}
//===----------------------------------------------------------------------===//
// CatchSwitchInst Implementation
//===----------------------------------------------------------------------===//
CatchSwitchInst::CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest,
unsigned NumReservedValues,
const Twine &NameStr,
Instruction *InsertBefore)
: TerminatorInst(ParentPad->getType(), Instruction::CatchSwitch, nullptr, 0,
InsertBefore) {
if (UnwindDest)
++NumReservedValues;
init(ParentPad, UnwindDest, NumReservedValues + 1);
setName(NameStr);
}
CatchSwitchInst::CatchSwitchInst(Value *ParentPad, BasicBlock *UnwindDest,
unsigned NumReservedValues,
const Twine &NameStr, BasicBlock *InsertAtEnd)
: TerminatorInst(ParentPad->getType(), Instruction::CatchSwitch, nullptr, 0,
InsertAtEnd) {
if (UnwindDest)
++NumReservedValues;
init(ParentPad, UnwindDest, NumReservedValues + 1);
setName(NameStr);
}
CatchSwitchInst::CatchSwitchInst(const CatchSwitchInst &CSI)
: TerminatorInst(CSI.getType(), Instruction::CatchSwitch, nullptr,
CSI.getNumOperands()) {
init(CSI.getParentPad(), CSI.getUnwindDest(), CSI.getNumOperands());
setNumHungOffUseOperands(ReservedSpace);
Use *OL = getOperandList();
const Use *InOL = CSI.getOperandList();
for (unsigned I = 1, E = ReservedSpace; I != E; ++I)
OL[I] = InOL[I];
}
void CatchSwitchInst::init(Value *ParentPad, BasicBlock *UnwindDest,
unsigned NumReservedValues) {
assert(ParentPad && NumReservedValues);
ReservedSpace = NumReservedValues;
setNumHungOffUseOperands(UnwindDest ? 2 : 1);
allocHungoffUses(ReservedSpace);
Op<0>() = ParentPad;
if (UnwindDest) {
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
setUnwindDest(UnwindDest);
}
}
/// growOperands - grow operands - This grows the operand list in response to a
/// push_back style of operation. This grows the number of ops by 2 times.
void CatchSwitchInst::growOperands(unsigned Size) {
unsigned NumOperands = getNumOperands();
assert(NumOperands >= 1);
if (ReservedSpace >= NumOperands + Size)
return;
ReservedSpace = (NumOperands + Size / 2) * 2;
growHungoffUses(ReservedSpace);
}
void CatchSwitchInst::addHandler(BasicBlock *Handler) {
unsigned OpNo = getNumOperands();
growOperands(1);
assert(OpNo < ReservedSpace && "Growing didn't work!");
setNumHungOffUseOperands(getNumOperands() + 1);
getOperandList()[OpNo] = Handler;
}
void CatchSwitchInst::removeHandler(handler_iterator HI) {
// Move all subsequent handlers up one.
Use *EndDst = op_end() - 1;
for (Use *CurDst = HI.getCurrent(); CurDst != EndDst; ++CurDst)
*CurDst = *(CurDst + 1);
// Null out the last handler use.
*EndDst = nullptr;
setNumHungOffUseOperands(getNumOperands() - 1);
}
//===----------------------------------------------------------------------===//
// FuncletPadInst Implementation
//===----------------------------------------------------------------------===//
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());
setParentPad(ParentPad);
setName(NameStr);
}
FuncletPadInst::FuncletPadInst(const FuncletPadInst &FPI)
: Instruction(FPI.getType(), FPI.getOpcode(),
OperandTraits<FuncletPadInst>::op_end(this) -
FPI.getNumOperands(),
FPI.getNumOperands()) {
std::copy(FPI.op_begin(), FPI.op_end(), op_begin());
setParentPad(FPI.getParentPad());
}
FuncletPadInst::FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
ArrayRef<Value *> Args, unsigned Values,
const Twine &NameStr, Instruction *InsertBefore)
: Instruction(ParentPad->getType(), Op,
OperandTraits<FuncletPadInst>::op_end(this) - Values, Values,
InsertBefore) {
init(ParentPad, Args, NameStr);
}
FuncletPadInst::FuncletPadInst(Instruction::FuncletPadOps Op, Value *ParentPad,
ArrayRef<Value *> Args, unsigned Values,
const Twine &NameStr, BasicBlock *InsertAtEnd)
: Instruction(ParentPad->getType(), Op,
OperandTraits<FuncletPadInst>::op_end(this) - Values, Values,
InsertAtEnd) {
init(ParentPad, Args, NameStr);
}
//===----------------------------------------------------------------------===//
// UnreachableInst Implementation
//===----------------------------------------------------------------------===//
UnreachableInst::UnreachableInst(LLVMContext &Context,
Instruction *InsertBefore)
: TerminatorInst(Type::getVoidTy(Context), Instruction::Unreachable,
nullptr, 0, InsertBefore) {
}
UnreachableInst::UnreachableInst(LLVMContext &Context, BasicBlock *InsertAtEnd)
: TerminatorInst(Type::getVoidTy(Context), Instruction::Unreachable,
nullptr, 0, InsertAtEnd) {
}
//===----------------------------------------------------------------------===//
// BranchInst Implementation
//===----------------------------------------------------------------------===//
void BranchInst::AssertOK() {
if (isConditional())
assert(getCondition()->getType()->isIntegerTy(1) &&
"May only branch on boolean predicates!");
}
BranchInst::BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore)
: TerminatorInst(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) {
Op<-1>() = IfTrue;
Op<-2>() = IfFalse;
Op<-3>() = Cond;
#ifndef NDEBUG
AssertOK();
#endif
}
BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd)
: TerminatorInst(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) {
Op<-1>() = IfTrue;
Op<-2>() = IfFalse;
Op<-3>() = Cond;
#ifndef NDEBUG
AssertOK();
#endif
}
BranchInst::BranchInst(const BranchInst &BI) :
TerminatorInst(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!");
Op<-3>() = BI.Op<-3>();
Op<-2>() = BI.Op<-2>();
}
SubclassOptionalData = BI.SubclassOptionalData;
}
void BranchInst::swapSuccessors() {
assert(isConditional() &&
"Cannot swap successors of an unconditional branch");
Op<-1>().swap(Op<-2>());
// Update profile metadata if present and it matches our structural
// expectations.
swapProfMetadata();
}
//===----------------------------------------------------------------------===//
// AllocaInst Implementation
//===----------------------------------------------------------------------===//
static Value *getAISize(LLVMContext &Context, Value *Amt) {
if (!Amt)
Amt = ConstantInt::get(Type::getInt32Ty(Context), 1);
else {
assert(!isa<BasicBlock>(Amt) &&
"Passed basic block into allocation size parameter! Use other ctor");
assert(Amt->getType()->isIntegerTy() &&
"Allocation array size is not an integer!");
}
return Amt;
}
AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, const Twine &Name,
Instruction *InsertBefore)
: AllocaInst(Ty, AddrSpace, /*ArraySize=*/nullptr, Name, InsertBefore) {}
AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, const Twine &Name,
BasicBlock *InsertAtEnd)
: AllocaInst(Ty, AddrSpace, /*ArraySize=*/nullptr, Name, InsertAtEnd) {}
AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize,
const Twine &Name, Instruction *InsertBefore)
: AllocaInst(Ty, AddrSpace, ArraySize, /*Align=*/0, Name, InsertBefore) {}
AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize,
const Twine &Name, BasicBlock *InsertAtEnd)
: AllocaInst(Ty, AddrSpace, ArraySize, /*Align=*/0, Name, InsertAtEnd) {}
AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize,
unsigned Align, const Twine &Name,
Instruction *InsertBefore)
: UnaryInstruction(PointerType::get(Ty, AddrSpace), Alloca,
getAISize(Ty->getContext(), ArraySize), InsertBefore),
AllocatedType(Ty) {
setAlignment(Align);
assert(!Ty->isVoidTy() && "Cannot allocate void!");
setName(Name);
}
AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize,
unsigned Align, const Twine &Name,
BasicBlock *InsertAtEnd)
: UnaryInstruction(PointerType::get(Ty, AddrSpace), Alloca,
getAISize(Ty->getContext(), ArraySize), InsertAtEnd),
AllocatedType(Ty) {
setAlignment(Align);
assert(!Ty->isVoidTy() && "Cannot allocate void!");
setName(Name);
}
void AllocaInst::setAlignment(unsigned Align) {
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
assert(Align <= MaximumAlignment &&
"Alignment is greater than MaximumAlignment!");
setInstructionSubclassData((getSubclassDataFromInstruction() & ~31) |
(Log2_32(Align) + 1));
assert(getAlignment() == Align && "Alignment representation error!");
}
bool AllocaInst::isArrayAllocation() const {
if (ConstantInt *CI = dyn_cast<ConstantInt>(getOperand(0)))
return !CI->isOne();
return true;
}
/// isStaticAlloca - Return true if this alloca is in the entry block of the
/// function and is a constant size. If so, the code generator will fold it
/// into the prolog/epilog code, so it is basically free.
bool AllocaInst::isStaticAlloca() const {
// Must be constant size.
if (!isa<ConstantInt>(getArraySize())) return false;
// Must be in the entry block.
const BasicBlock *Parent = getParent();
return Parent == &Parent->getParent()->front() && !isUsedWithInAlloca();
}
//===----------------------------------------------------------------------===//
// LoadInst Implementation
//===----------------------------------------------------------------------===//
void LoadInst::AssertOK() {
assert(getOperand(0)->getType()->isPointerTy() &&
"Ptr must have pointer type.");
assert(!(isAtomic() && getAlignment() == 0) &&
"Alignment required for atomic load");
}
LoadInst::LoadInst(Value *Ptr, const Twine &Name, Instruction *InsertBef)
: LoadInst(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, bool isVolatile,
Instruction *InsertBef)
: LoadInst(Ty, Ptr, Name, isVolatile, /*Align=*/0, InsertBef) {}
LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
BasicBlock *InsertAE)
: LoadInst(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,
unsigned Align, BasicBlock *InsertAE)
: LoadInst(Ptr, Name, isVolatile, Align, AtomicOrdering::NotAtomic,
SyncScope::System, InsertAE) {}
LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile,
unsigned Align, AtomicOrdering Order,
SyncScope::ID SSID, Instruction *InsertBef)
: UnaryInstruction(Ty, Load, Ptr, InsertBef) {
assert(Ty == cast<PointerType>(Ptr->getType())->getElementType());
setVolatile(isVolatile);
setAlignment(Align);
setAtomic(Order, SSID);
AssertOK();
setName(Name);
}
LoadInst::LoadInst(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) {
setVolatile(isVolatile);
setAlignment(Align);
setAtomic(Order, SSID);
AssertOK();
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 &&
"Alignment is greater than MaximumAlignment!");
setInstructionSubclassData((getSubclassDataFromInstruction() & ~(31 << 1)) |
((Log2_32(Align)+1)<<1));
assert(getAlignment() == Align && "Alignment representation error!");
}
//===----------------------------------------------------------------------===//
// StoreInst Implementation
//===----------------------------------------------------------------------===//
void StoreInst::AssertOK() {
assert(getOperand(0) && getOperand(1) && "Both operands must be non-null!");
assert(getOperand(1)->getType()->isPointerTy() &&
"Ptr must have pointer type!");
assert(getOperand(0)->getType() ==
cast<PointerType>(getOperand(1)->getType())->getElementType()
&& "Ptr must be a pointer to Val type!");
assert(!(isAtomic() && getAlignment() == 0) &&
"Alignment required for atomic store");
}
StoreInst::StoreInst(Value *val, Value *addr, Instruction *InsertBefore)
: StoreInst(val, addr, /*isVolatile=*/false, InsertBefore) {}
StoreInst::StoreInst(Value *val, Value *addr, BasicBlock *InsertAtEnd)
: StoreInst(val, addr, /*isVolatile=*/false, InsertAtEnd) {}
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
Instruction *InsertBefore)
: StoreInst(val, addr, isVolatile, /*Align=*/0, InsertBefore) {}
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
BasicBlock *InsertAtEnd)
: StoreInst(val, addr, isVolatile, /*Align=*/0, InsertAtEnd) {}
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, unsigned Align,
Instruction *InsertBefore)
: StoreInst(val, addr, isVolatile, Align, AtomicOrdering::NotAtomic,
SyncScope::System, InsertBefore) {}
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, unsigned Align,
BasicBlock *InsertAtEnd)
: StoreInst(val, addr, isVolatile, Align, AtomicOrdering::NotAtomic,
SyncScope::System, InsertAtEnd) {}
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
unsigned Align, AtomicOrdering Order,
SyncScope::ID SSID,
Instruction *InsertBefore)
: Instruction(Type::getVoidTy(val->getContext()), Store,
OperandTraits<StoreInst>::op_begin(this),
OperandTraits<StoreInst>::operands(this),
InsertBefore) {
Op<0>() = val;
Op<1>() = addr;
setVolatile(isVolatile);
setAlignment(Align);
setAtomic(Order, SSID);
AssertOK();
}
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
unsigned Align, AtomicOrdering Order,
SyncScope::ID SSID,
BasicBlock *InsertAtEnd)
: Instruction(Type::getVoidTy(val->getContext()), Store,
OperandTraits<StoreInst>::op_begin(this),
OperandTraits<StoreInst>::operands(this),
InsertAtEnd) {
Op<0>() = val;
Op<1>() = addr;
setVolatile(isVolatile);
setAlignment(Align);
setAtomic(Order, SSID);
AssertOK();
}
void StoreInst::setAlignment(unsigned Align) {
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
assert(Align <= MaximumAlignment &&
"Alignment is greater than MaximumAlignment!");
setInstructionSubclassData((getSubclassDataFromInstruction() & ~(31 << 1)) |
((Log2_32(Align)+1) << 1));
assert(getAlignment() == Align && "Alignment representation error!");
}
//===----------------------------------------------------------------------===//
// AtomicCmpXchgInst Implementation
//===----------------------------------------------------------------------===//
void AtomicCmpXchgInst::Init(Value *Ptr, Value *Cmp, Value *NewVal,
AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SyncScope::ID SSID) {
Op<0>() = Ptr;
Op<1>() = Cmp;
Op<2>() = NewVal;
setSuccessOrdering(SuccessOrdering);
setFailureOrdering(FailureOrdering);
setSyncScopeID(SSID);
assert(getOperand(0) && getOperand(1) && getOperand(2) &&
"All operands must be non-null!");
assert(getOperand(0)->getType()->isPointerTy() &&
"Ptr must have pointer type!");
assert(getOperand(1)->getType() ==
cast<PointerType>(getOperand(0)->getType())->getElementType()
&& "Ptr must be a pointer to Cmp type!");
assert(getOperand(2)->getType() ==
cast<PointerType>(getOperand(0)->getType())->getElementType()
&& "Ptr must be a pointer to NewVal type!");
assert(SuccessOrdering != AtomicOrdering::NotAtomic &&
"AtomicCmpXchg instructions must be atomic!");
assert(FailureOrdering != AtomicOrdering::NotAtomic &&
"AtomicCmpXchg instructions must be atomic!");
assert(!isStrongerThan(FailureOrdering, SuccessOrdering) &&
"AtomicCmpXchg failure argument shall be no stronger than the success "
"argument");
assert(FailureOrdering != AtomicOrdering::Release &&
FailureOrdering != AtomicOrdering::AcquireRelease &&
"AtomicCmpXchg failure ordering cannot include release semantics");
}
AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SyncScope::ID SSID,
Instruction *InsertBefore)
: Instruction(
StructType::get(Cmp->getType(), Type::getInt1Ty(Cmp->getContext())),
AtomicCmpXchg, OperandTraits<AtomicCmpXchgInst>::op_begin(this),
OperandTraits<AtomicCmpXchgInst>::operands(this), InsertBefore) {
Init(Ptr, Cmp, NewVal, SuccessOrdering, FailureOrdering, SSID);
}
AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SyncScope::ID SSID,
BasicBlock *InsertAtEnd)
: Instruction(
StructType::get(Cmp->getType(), Type::getInt1Ty(Cmp->getContext())),
AtomicCmpXchg, OperandTraits<AtomicCmpXchgInst>::op_begin(this),
OperandTraits<AtomicCmpXchgInst>::operands(this), InsertAtEnd) {
Init(Ptr, Cmp, NewVal, SuccessOrdering, FailureOrdering, SSID);
}
//===----------------------------------------------------------------------===//
// AtomicRMWInst Implementation
//===----------------------------------------------------------------------===//
void AtomicRMWInst::Init(BinOp Operation, Value *Ptr, Value *Val,
AtomicOrdering Ordering,
SyncScope::ID SSID) {
Op<0>() = Ptr;
Op<1>() = Val;
setOperation(Operation);
setOrdering(Ordering);
setSyncScopeID(SSID);
assert(getOperand(0) && getOperand(1) &&
"All operands must be non-null!");
assert(getOperand(0)->getType()->isPointerTy() &&
"Ptr must have pointer type!");
assert(getOperand(1)->getType() ==
cast<PointerType>(getOperand(0)->getType())->getElementType()
&& "Ptr must be a pointer to Val type!");
assert(Ordering != AtomicOrdering::NotAtomic &&
"AtomicRMW instructions must be atomic!");
}
AtomicRMWInst::AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
AtomicOrdering Ordering,
SyncScope::ID SSID,
Instruction *InsertBefore)
: Instruction(Val->getType(), AtomicRMW,
OperandTraits<AtomicRMWInst>::op_begin(this),
OperandTraits<AtomicRMWInst>::operands(this),
InsertBefore) {
Init(Operation, Ptr, Val, Ordering, SSID);
}
AtomicRMWInst::AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
AtomicOrdering Ordering,
SyncScope::ID SSID,
BasicBlock *InsertAtEnd)
: Instruction(Val->getType(), AtomicRMW,
OperandTraits<AtomicRMWInst>::op_begin(this),
OperandTraits<AtomicRMWInst>::operands(this),
InsertAtEnd) {
Init(Operation, Ptr, Val, Ordering, SSID);
}
//===----------------------------------------------------------------------===//
// FenceInst Implementation
//===----------------------------------------------------------------------===//
FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering,
SyncScope::ID SSID,
Instruction *InsertBefore)
: Instruction(Type::getVoidTy(C), Fence, nullptr, 0, InsertBefore) {
setOrdering(Ordering);
setSyncScopeID(SSID);
}
FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering,
SyncScope::ID SSID,
BasicBlock *InsertAtEnd)
: Instruction(Type::getVoidTy(C), Fence, nullptr, 0, InsertAtEnd) {
setOrdering(Ordering);
setSyncScopeID(SSID);
}
//===----------------------------------------------------------------------===//
// GetElementPtrInst Implementation
//===----------------------------------------------------------------------===//
void GetElementPtrInst::init(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name) {
assert(getNumOperands() == 1 + IdxList.size() &&
"NumOperands not initialized?");
Op<0>() = Ptr;
std::copy(IdxList.begin(), IdxList.end(), op_begin() + 1);
setName(Name);
}
GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI)
: Instruction(GEPI.getType(), GetElementPtr,
OperandTraits<GetElementPtrInst>::op_end(this) -
GEPI.getNumOperands(),
GEPI.getNumOperands()),
SourceElementType(GEPI.SourceElementType),
ResultElementType(GEPI.ResultElementType) {
std::copy(GEPI.op_begin(), GEPI.op_end(), op_begin());
SubclassOptionalData = GEPI.SubclassOptionalData;
}
/// getIndexedType - Returns the type of the element that would be accessed with
/// a gep instruction with the specified parameters.
///
/// The Idxs pointer should point to a continuous piece of memory containing the
/// indices, either as Value* or uint64_t.
///
/// A null type is returned if the indices are invalid for the specified
/// pointer type.
///
template <typename IndexTy>
static Type *getIndexedTypeInternal(Type *Agg, ArrayRef<IndexTy> IdxList) {
// Handle the special case of the empty set index set, which is always valid.
if (IdxList.empty())
return Agg;
// If there is at least one index, the top level type must be sized, otherwise
// it cannot be 'stepped over'.
if (!Agg->isSized())
return nullptr;
unsigned CurIdx = 1;
for (; CurIdx != IdxList.size(); ++CurIdx) {
CompositeType *CT = dyn_cast<CompositeType>(Agg);
if (!CT || CT->isPointerTy()) return nullptr;
IndexTy Index = IdxList[CurIdx];
if (!CT->indexValid(Index)) return nullptr;
Agg = CT->getTypeAtIndex(Index);
}
return CurIdx == IdxList.size() ? Agg : nullptr;
}
Type *GetElementPtrInst::getIndexedType(Type *Ty, ArrayRef<Value *> IdxList) {
return getIndexedTypeInternal(Ty, IdxList);
}
Type *GetElementPtrInst::getIndexedType(Type *Ty,
ArrayRef<Constant *> IdxList) {
return getIndexedTypeInternal(Ty, IdxList);
}
Type *GetElementPtrInst::getIndexedType(Type *Ty, ArrayRef<uint64_t> IdxList) {
return getIndexedTypeInternal(Ty, IdxList);
}
/// hasAllZeroIndices - Return true if all of the indices of this GEP are
/// zeros. If so, the result pointer and the first operand have the same
/// value, just potentially different types.
bool GetElementPtrInst::hasAllZeroIndices() const {
for (unsigned i = 1, e = getNumOperands(); i != e; ++i) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(getOperand(i))) {
if (!CI->isZero()) return false;
} else {
return false;
}
}
return true;
}
/// hasAllConstantIndices - Return true if all of the indices of this GEP are
/// constant integers. If so, the result pointer and the first operand have
/// a constant offset between them.
bool GetElementPtrInst::hasAllConstantIndices() const {
for (unsigned i = 1, e = getNumOperands(); i != e; ++i) {
if (!isa<ConstantInt>(getOperand(i)))
return false;
}
return true;
}
void GetElementPtrInst::setIsInBounds(bool B) {
cast<GEPOperator>(this)->setIsInBounds(B);
}
bool GetElementPtrInst::isInBounds() const {
return cast<GEPOperator>(this)->isInBounds();
}
bool GetElementPtrInst::accumulateConstantOffset(const DataLayout &DL,
APInt &Offset) const {
// Delegate to the generic GEPOperator implementation.
return cast<GEPOperator>(this)->accumulateConstantOffset(DL, Offset);
}
//===----------------------------------------------------------------------===//
// ExtractElementInst Implementation
//===----------------------------------------------------------------------===//
ExtractElementInst::ExtractElementInst(Value *Val, Value *Index,
const Twine &Name,
Instruction *InsertBef)
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
ExtractElement,
OperandTraits<ExtractElementInst>::op_begin(this),
2, InsertBef) {
assert(isValidOperands(Val, Index) &&
"Invalid extractelement instruction operands!");
Op<0>() = Val;
Op<1>() = Index;
setName(Name);
}
ExtractElementInst::ExtractElementInst(Value *Val, Value *Index,
const Twine &Name,
BasicBlock *InsertAE)
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
ExtractElement,
OperandTraits<ExtractElementInst>::op_begin(this),
2, InsertAE) {
assert(isValidOperands(Val, Index) &&
"Invalid extractelement instruction operands!");
Op<0>() = Val;
Op<1>() = Index;
setName(Name);
}
bool ExtractElementInst::isValidOperands(const Value *Val, const Value *Index) {
if (!Val->getType()->isVectorTy() || !Index->getType()->isIntegerTy())
return false;
return true;
}
//===----------------------------------------------------------------------===//
// InsertElementInst Implementation
//===----------------------------------------------------------------------===//
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index,
const Twine &Name,
Instruction *InsertBef)
: Instruction(Vec->getType(), InsertElement,
OperandTraits<InsertElementInst>::op_begin(this),
3, InsertBef) {
assert(isValidOperands(Vec, Elt, Index) &&
"Invalid insertelement instruction operands!");
Op<0>() = Vec;
Op<1>() = Elt;
Op<2>() = Index;
setName(Name);
}
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index,
const Twine &Name,
BasicBlock *InsertAE)
: Instruction(Vec->getType(), InsertElement,
OperandTraits<InsertElementInst>::op_begin(this),
3, InsertAE) {
assert(isValidOperands(Vec, Elt, Index) &&
"Invalid insertelement instruction operands!");
Op<0>() = Vec;
Op<1>() = Elt;
Op<2>() = Index;
setName(Name);
}
bool InsertElementInst::isValidOperands(const Value *Vec, const Value *Elt,
const Value *Index) {
if (!Vec->getType()->isVectorTy())
return false; // First operand of insertelement must be vector type.
if (Elt->getType() != cast<VectorType>(Vec->getType())->getElementType())
return false;// Second operand of insertelement must be vector element type.
if (!Index->getType()->isIntegerTy())
return false; // Third operand of insertelement must be i32.
return true;
}
//===----------------------------------------------------------------------===//
// ShuffleVectorInst Implementation
//===----------------------------------------------------------------------===//
ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
const Twine &Name,
Instruction *InsertBefore)
: Instruction(VectorType::get(cast<VectorType>(V1->getType())->getElementType(),
cast<VectorType>(Mask->getType())->getNumElements()),
ShuffleVector,
OperandTraits<ShuffleVectorInst>::op_begin(this),
OperandTraits<ShuffleVectorInst>::operands(this),
InsertBefore) {
assert(isValidOperands(V1, V2, Mask) &&
"Invalid shuffle vector instruction operands!");
Op<0>() = V1;
Op<1>() = V2;
Op<2>() = Mask;
setName(Name);
}
ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
const Twine &Name,
BasicBlock *InsertAtEnd)
: Instruction(VectorType::get(cast<VectorType>(V1->getType())->getElementType(),
cast<VectorType>(Mask->getType())->getNumElements()),
ShuffleVector,
OperandTraits<ShuffleVectorInst>::op_begin(this),
OperandTraits<ShuffleVectorInst>::operands(this),
InsertAtEnd) {
assert(isValidOperands(V1, V2, Mask) &&
"Invalid shuffle vector instruction operands!");
Op<0>() = V1;
Op<1>() = V2;
Op<2>() = Mask;
setName(Name);
}
bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2,
const Value *Mask) {
// V1 and V2 must be vectors of the same type.
if (!V1->getType()->isVectorTy() || V1->getType() != V2->getType())
return false;
// Mask must be vector of i32.
auto *MaskTy = dyn_cast<VectorType>(Mask->getType());
if (!MaskTy || !MaskTy->getElementType()->isIntegerTy(32))
return false;
// Check to see if Mask is valid.
if (isa<UndefValue>(Mask) || isa<ConstantAggregateZero>(Mask))
return true;
if (const auto *MV = dyn_cast<ConstantVector>(Mask)) {
unsigned V1Size = cast<VectorType>(V1->getType())->getNumElements();
for (Value *Op : MV->operands()) {
if (auto *CI = dyn_cast<ConstantInt>(Op)) {
if (CI->uge(V1Size*2))
return false;
} else if (!isa<UndefValue>(Op)) {
return false;
}
}
return true;
}
if (const auto *CDS = dyn_cast<ConstantDataSequential>(Mask)) {
unsigned V1Size = cast<VectorType>(V1->getType())->getNumElements();
for (unsigned i = 0, e = MaskTy->getNumElements(); i != e; ++i)
if (CDS->getElementAsInteger(i) >= V1Size*2)
return false;
return true;
}
// The bitcode reader can create a place holder for a forward reference
// used as the shuffle mask. When this occurs, the shuffle mask will
// fall into this case and fail. To avoid this error, do this bit of
// ugliness to allow such a mask pass.
if (const auto *CE = dyn_cast<ConstantExpr>(Mask))
if (CE->getOpcode() == Instruction::UserOp1)
return true;
return false;
}
int ShuffleVectorInst::getMaskValue(Constant *Mask, unsigned i) {
assert(i < Mask->getType()->getVectorNumElements() && "Index out of range");
if (auto *CDS = dyn_cast<ConstantDataSequential>(Mask))
return CDS->getElementAsInteger(i);
Constant *C = Mask->getAggregateElement(i);
if (isa<UndefValue>(C))
return -1;
return cast<ConstantInt>(C)->getZExtValue();
}
void ShuffleVectorInst::getShuffleMask(Constant *Mask,
SmallVectorImpl<int> &Result) {
unsigned NumElts = Mask->getType()->getVectorNumElements();
if (auto *CDS = dyn_cast<ConstantDataSequential>(Mask)) {
for (unsigned i = 0; i != NumElts; ++i)
Result.push_back(CDS->getElementAsInteger(i));
return;
}
for (unsigned i = 0; i != NumElts; ++i) {
Constant *C = Mask->getAggregateElement(i);
Result.push_back(isa<UndefValue>(C) ? -1 :
cast<ConstantInt>(C)->getZExtValue());
}
}
//===----------------------------------------------------------------------===//
// InsertValueInst Class
//===----------------------------------------------------------------------===//
void InsertValueInst::init(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
const Twine &Name) {
assert(getNumOperands() == 2 && "NumOperands not initialized?");
// There's no fundamental reason why we require at least one index
// (other than weirdness with &*IdxBegin being invalid; see
// getelementptr's init routine for example). But there's no
// present need to support it.
assert(!Idxs.empty() && "InsertValueInst must have at least one index");
assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs) ==
Val->getType() && "Inserted value must match indexed type!");
Op<0>() = Agg;
Op<1>() = Val;
Indices.append(Idxs.begin(), Idxs.end());
setName(Name);
}
InsertValueInst::InsertValueInst(const InsertValueInst &IVI)
: Instruction(IVI.getType(), InsertValue,
OperandTraits<InsertValueInst>::op_begin(this), 2),
Indices(IVI.Indices) {
Op<0>() = IVI.getOperand(0);
Op<1>() = IVI.getOperand(1);
SubclassOptionalData = IVI.SubclassOptionalData;
}
//===----------------------------------------------------------------------===//
// ExtractValueInst Class
//===----------------------------------------------------------------------===//
void ExtractValueInst::init(ArrayRef<unsigned> Idxs, const Twine &Name) {
assert(getNumOperands() == 1 && "NumOperands not initialized?");
// There's no fundamental reason why we require at least one index.
// But there's no present need to support it.
assert(!Idxs.empty() && "ExtractValueInst must have at least one index");
Indices.append(Idxs.begin(), Idxs.end());
setName(Name);
}
ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
: UnaryInstruction(EVI.getType(), ExtractValue, EVI.getOperand(0)),
Indices(EVI.Indices) {
SubclassOptionalData = EVI.SubclassOptionalData;
}
// 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.
//
Type *ExtractValueInst::getIndexedType(Type *Agg,
ArrayRef<unsigned> Idxs) {
for (unsigned Index : Idxs) {
// We can't use CompositeType::indexValid(Index) here.
// indexValid() always returns true for arrays because getelementptr allows
// out-of-bounds indices. Since we don't allow those for extractvalue and
// insertvalue we need to check array indexing manually.
// Since the only other types we can index into are struct types it's just
// as easy to check those manually as well.
if (ArrayType *AT = dyn_cast<ArrayType>(Agg)) {
if (Index >= AT->getNumElements())
return nullptr;
} else if (StructType *ST = dyn_cast<StructType>(Agg)) {
if (Index >= ST->getNumElements())
return nullptr;
} else {
// Not a valid type to index into.
return nullptr;
}
Agg = cast<CompositeType>(Agg)->getTypeAtIndex(Index);
}
return const_cast<Type*>(Agg);
}
//===----------------------------------------------------------------------===//
// BinaryOperator Class
//===----------------------------------------------------------------------===//
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
Type *Ty, const Twine &Name,
Instruction *InsertBefore)
: Instruction(Ty, iType,
OperandTraits<BinaryOperator>::op_begin(this),
OperandTraits<BinaryOperator>::operands(this),
InsertBefore) {
Op<0>() = S1;
Op<1>() = S2;
setName(Name);
AssertOK();
}
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
Type *Ty, const Twine &Name,
BasicBlock *InsertAtEnd)
: Instruction(Ty, iType,
OperandTraits<BinaryOperator>::op_begin(this),
OperandTraits<BinaryOperator>::operands(this),
InsertAtEnd) {
Op<0>() = S1;
Op<1>() = S2;
setName(Name);
AssertOK();
}
void BinaryOperator::AssertOK() {
Value *LHS = getOperand(0), *RHS = getOperand(1);
(void)LHS; (void)RHS; // Silence warnings.
assert(LHS->getType() == RHS->getType() &&
"Binary operator operand types must match!");
#ifndef NDEBUG
switch (getOpcode()) {
case Add: case Sub:
case Mul:
assert(getType() == LHS->getType() &&
"Arithmetic operation should return same type as operands!");
assert(getType()->isIntOrIntVectorTy() &&
"Tried to create an integer operation on a non-integer type!");
break;
case FAdd: case FSub:
case FMul:
assert(getType() == LHS->getType() &&
"Arithmetic operation should return same type as operands!");
assert(getType()->isFPOrFPVectorTy() &&
"Tried to create a floating-point operation on a "
"non-floating-point type!");
break;
case UDiv:
case SDiv:
assert(getType() == LHS->getType() &&
"Arithmetic operation should return same type as operands!");
assert(getType()->isIntOrIntVectorTy() &&
"Incorrect operand type (not integer) for S/UDIV");
break;
case FDiv:
assert(getType() == LHS->getType() &&
"Arithmetic operation should return same type as operands!");
assert(getType()->isFPOrFPVectorTy() &&
"Incorrect operand type (not floating point) for FDIV");
break;
case URem:
case SRem:
assert(getType() == LHS->getType() &&
"Arithmetic operation should return same type as operands!");
assert(getType()->isIntOrIntVectorTy() &&
"Incorrect operand type (not integer) for S/UREM");
break;
case FRem:
assert(getType() == LHS->getType() &&
"Arithmetic operation should return same type as operands!");
assert(getType()->isFPOrFPVectorTy() &&
"Incorrect operand type (not floating point) for FREM");
break;
case Shl:
case LShr:
case AShr:
assert(getType() == LHS->getType() &&
"Shift operation should return same type as operands!");
assert(getType()->isIntOrIntVectorTy() &&
"Tried to create a shift operation on a non-integral type!");
break;
case And: case Or:
case Xor:
assert(getType() == LHS->getType() &&
"Logical operation should return same type as operands!");
assert(getType()->isIntOrIntVectorTy() &&
"Tried to create a logical operation on a non-integral type!");
break;
default: llvm_unreachable("Invalid opcode provided");
}
#endif
}
BinaryOperator *BinaryOperator::Create(BinaryOps Op, Value *S1, Value *S2,
const Twine &Name,
Instruction *InsertBefore) {
assert(S1->getType() == S2->getType() &&
"Cannot create binary operator with two operands of differing type!");
return new BinaryOperator(Op, S1, S2, S1->getType(), Name, InsertBefore);
}
BinaryOperator *BinaryOperator::Create(BinaryOps Op, Value *S1, Value *S2,
const Twine &Name,
BasicBlock *InsertAtEnd) {
BinaryOperator *Res = Create(Op, S1, S2, Name);
InsertAtEnd->getInstList().push_back(Res);
return Res;
}
BinaryOperator *BinaryOperator::CreateNeg(Value *Op, const Twine &Name,
Instruction *InsertBefore) {
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
return new BinaryOperator(Instruction::Sub,
zero, Op,
Op->getType(), Name, InsertBefore);
}
BinaryOperator *BinaryOperator::CreateNeg(Value *Op, const Twine &Name,
BasicBlock *InsertAtEnd) {
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
return new BinaryOperator(Instruction::Sub,
zero, Op,
Op->getType(), Name, InsertAtEnd);
}
BinaryOperator *BinaryOperator::CreateNSWNeg(Value *Op, const Twine &Name,
Instruction *InsertBefore) {
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
return BinaryOperator::CreateNSWSub(zero, Op, Name, InsertBefore);
}
BinaryOperator *BinaryOperator::CreateNSWNeg(Value *Op, const Twine &Name,
BasicBlock *InsertAtEnd) {
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
return BinaryOperator::CreateNSWSub(zero, Op, Name, InsertAtEnd);
}
BinaryOperator *BinaryOperator::CreateNUWNeg(Value *Op, const Twine &Name,
Instruction *InsertBefore) {
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
return BinaryOperator::CreateNUWSub(zero, Op, Name, InsertBefore);
}
BinaryOperator *BinaryOperator::CreateNUWNeg(Value *Op, const Twine &Name,
BasicBlock *InsertAtEnd) {
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
return BinaryOperator::CreateNUWSub(zero, Op, Name, InsertAtEnd);
}
BinaryOperator *BinaryOperator::CreateFNeg(Value *Op, const Twine &Name,
Instruction *InsertBefore) {
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
return new BinaryOperator(Instruction::FSub, zero, Op,
Op->getType(), Name, InsertBefore);
}
BinaryOperator *BinaryOperator::CreateFNeg(Value *Op, const Twine &Name,
BasicBlock *InsertAtEnd) {
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
return new BinaryOperator(Instruction::FSub, zero, Op,
Op->getType(), Name, InsertAtEnd);
}
BinaryOperator *BinaryOperator::CreateNot(Value *Op, const Twine &Name,
Instruction *InsertBefore) {
Constant *C = Constant::getAllOnesValue(Op->getType());
return new BinaryOperator(Instruction::Xor, Op, C,
Op->getType(), Name, InsertBefore);
}
BinaryOperator *BinaryOperator::CreateNot(Value *Op, const Twine &Name,
BasicBlock *InsertAtEnd) {
Constant *AllOnes = Constant::getAllOnesValue(Op->getType());
return new BinaryOperator(Instruction::Xor, Op, AllOnes,
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
// is changed.
bool BinaryOperator::swapOperands() {
if (!isCommutative())
return true; // Can't commute operands
Op<0>().swap(Op<1>());
return false;
}
//===----------------------------------------------------------------------===//
// FPMathOperator Class
//===----------------------------------------------------------------------===//
float FPMathOperator::getFPAccuracy() const {
const MDNode *MD =
cast<Instruction>(this)->getMetadata(LLVMContext::MD_fpmath);
if (!MD)
return 0.0;
ConstantFP *Accuracy = mdconst::extract<ConstantFP>(MD->getOperand(0));
return Accuracy->getValueAPF().convertToFloat();
}
//===----------------------------------------------------------------------===//
// CastInst Class
//===----------------------------------------------------------------------===//
// Just determine if this cast only deals with integral->integral conversion.
bool CastInst::isIntegerCast() const {
switch (getOpcode()) {
default: return false;
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::Trunc:
return true;
case Instruction::BitCast:
return getOperand(0)->getType()->isIntegerTy() &&
getType()->isIntegerTy();
}
}
bool CastInst::isLosslessCast() const {
// Only BitCast can be lossless, exit fast if we're not BitCast
if (getOpcode() != Instruction::BitCast)
return false;
// Identity cast is always lossless
Type *SrcTy = getOperand(0)->getType();
Type *DstTy = getType();
if (SrcTy == DstTy)
return true;
// Pointer to pointer is always lossless.
if (SrcTy->isPointerTy())
return DstTy->isPointerTy();
return false; // Other types have no identity values
}
/// This function determines if the CastInst does not require any bits to be
/// changed in order to effect the cast. Essentially, it identifies cases where
/// no code gen is necessary for the cast, hence the name no-op cast. For
/// example, the following are all no-op casts:
/// # bitcast i32* %x to i8*
/// # bitcast <2 x i32> %x to <4 x i16>
/// # ptrtoint i32* %x to i32 ; on 32-bit plaforms only
/// @brief Determine if the described cast is a no-op.
bool CastInst::isNoopCast(Instruction::CastOps Opcode,
Type *SrcTy,
Type *DestTy,
Type *IntPtrTy) {
switch (Opcode) {
default: llvm_unreachable("Invalid CastOp");
case Instruction::Trunc:
case Instruction::ZExt:
case Instruction::SExt:
case Instruction::FPTrunc:
case Instruction::FPExt:
case Instruction::UIToFP:
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
case Instruction::AddrSpaceCast:
// TODO: Target informations may give a more accurate answer here.
return false;
case Instruction::BitCast:
return true; // BitCast never modifies bits.
case Instruction::PtrToInt:
return IntPtrTy->getScalarSizeInBits() ==
DestTy->getScalarSizeInBits();
case Instruction::IntToPtr:
return IntPtrTy->getScalarSizeInBits() ==
SrcTy->getScalarSizeInBits();
}
}
/// @brief Determine if a cast is a no-op.
bool CastInst::isNoopCast(Type *IntPtrTy) const {
return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), IntPtrTy);
}
bool CastInst::isNoopCast(const DataLayout &DL) const {
Type *PtrOpTy = nullptr;
if (getOpcode() == Instruction::PtrToInt)
PtrOpTy = getOperand(0)->getType();
else if (getOpcode() == Instruction::IntToPtr)
PtrOpTy = getType();
Type *IntPtrTy =
PtrOpTy ? DL.getIntPtrType(PtrOpTy) : DL.getIntPtrType(getContext(), 0);
return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), IntPtrTy);
}
/// This function determines if a pair of casts can be eliminated and what
/// opcode should be used in the elimination. This assumes that there are two
/// instructions like this:
/// * %F = firstOpcode SrcTy %x to MidTy
/// * %S = secondOpcode MidTy %F to DstTy
/// The function returns a resultOpcode so these two casts can be replaced with:
/// * %Replacement = resultOpcode %SrcTy %x to DstTy
/// If no such cast is permitted, the function returns 0.
unsigned CastInst::isEliminableCastPair(
Instruction::CastOps firstOp, Instruction::CastOps secondOp,
Type *SrcTy, Type *MidTy, Type *DstTy, Type *SrcIntPtrTy, Type *MidIntPtrTy,
Type *DstIntPtrTy) {
// Define the 144 possibilities for these two cast instructions. The values
// in this matrix determine what to do in a given situation and select the
// case in the switch below. The rows correspond to firstOp, the columns
// correspond to secondOp. In looking at the table below, keep in mind
// the following cast properties:
//
// Size Compare Source Destination
// Operator Src ? Size Type Sign Type Sign
// -------- ------------ ------------------- ---------------------
// TRUNC > Integer Any Integral Any
// ZEXT < Integral Unsigned Integer Any
// SEXT < Integral Signed Integer Any
// FPTOUI n/a FloatPt n/a Integral Unsigned
// FPTOSI n/a FloatPt n/a Integral Signed
// UITOFP n/a Integral Unsigned FloatPt n/a
// SITOFP n/a Integral Signed FloatPt n/a
// FPTRUNC > FloatPt n/a FloatPt n/a
// FPEXT < FloatPt n/a FloatPt n/a
// PTRTOINT n/a Pointer n/a Integral Unsigned
// INTTOPTR n/a Integral Unsigned Pointer n/a
// BITCAST = FirstClass n/a FirstClass n/a
// ADDRSPCST n/a Pointer n/a Pointer n/a
//
// NOTE: some transforms are safe, but we consider them to be non-profitable.
// For example, we could merge "fptoui double to i32" + "zext i32 to i64",
// into "fptoui double to i64", but this loses information about the range
// of the produced value (we no longer know the top-part is all zeros).
// Further this conversion is often much more expensive for typical hardware,
// and causes issues when building libgcc. We disallow fptosi+sext for the
// same reason.
const unsigned numCastOps =
Instruction::CastOpsEnd - Instruction::CastOpsBegin;
static const uint8_t CastResults[numCastOps][numCastOps] = {
// T F F U S F F P I B A -+
// R Z S P P I I T P 2 N T S |
// U E E 2 2 2 2 R E I T C C +- secondOp
// N X X U S F F N X N 2 V V |
// C T T I I P P C T T P T T -+
{ 1, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // Trunc -+
{ 8, 1, 9,99,99, 2,17,99,99,99, 2, 3, 0}, // ZExt |
{ 8, 0, 1,99,99, 0, 2,99,99,99, 0, 3, 0}, // SExt |
{ 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // FPToUI |
{ 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // FPToSI |
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // UIToFP +- firstOp
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // SIToFP |
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // FPTrunc |
{ 99,99,99, 2, 2,99,99,10, 2,99,99, 4, 0}, // FPExt |
{ 1, 0, 0,99,99, 0, 0,99,99,99, 7, 3, 0}, // PtrToInt |
{ 99,99,99,99,99,99,99,99,99,11,99,15, 0}, // IntToPtr |
{ 5, 5, 5, 6, 6, 5, 5, 6, 6,16, 5, 1,14}, // BitCast |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,13,12}, // AddrSpaceCast -+
};
// TODO: This logic could be encoded into the table above and handled in the
// switch below.
// If either of the casts are a bitcast from scalar to vector, disallow the
// merging. However, any pair of bitcasts are allowed.
bool IsFirstBitcast = (firstOp == Instruction::BitCast);
bool IsSecondBitcast = (secondOp == Instruction::BitCast);
bool AreBothBitcasts = IsFirstBitcast && IsSecondBitcast;
// Check if any of the casts convert scalars <-> vectors.
if ((IsFirstBitcast && isa<VectorType>(SrcTy) != isa<VectorType>(MidTy)) ||
(IsSecondBitcast && isa<VectorType>(MidTy) != isa<VectorType>(DstTy)))
if (!AreBothBitcasts)
return 0;
int ElimCase = CastResults[firstOp-Instruction::CastOpsBegin]
[secondOp-Instruction::CastOpsBegin];
switch (ElimCase) {
case 0:
// Categorically disallowed.
return 0;
case 1:
// Allowed, use first cast's opcode.
return firstOp;
case 2:
// Allowed, use second cast's opcode.
return secondOp;
case 3:
// No-op cast in second op implies firstOp as long as the DestTy
// is integer and we are not converting between a vector and a
// non-vector type.
if (!SrcTy->isVectorTy() && DstTy->isIntegerTy())
return firstOp;
return 0;
case 4:
// No-op cast in second op implies firstOp as long as the DestTy
// is floating point.
if (DstTy->isFloatingPointTy())
return firstOp;
return 0;
case 5:
// No-op cast in first op implies secondOp as long as the SrcTy
// is an integer.
if (SrcTy->isIntegerTy())
return secondOp;
return 0;
case 6:
// No-op cast in first op implies secondOp as long as the SrcTy
// is a floating point.
if (SrcTy->isFloatingPointTy())
return secondOp;
return 0;
case 7: {
// Cannot simplify if address spaces are different!
if (SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace())
return 0;
unsigned MidSize = MidTy->getScalarSizeInBits();
// We can still fold this without knowing the actual sizes as long we
// know that the intermediate pointer is the largest possible
// pointer size.
// FIXME: Is this always true?
if (MidSize == 64)
return Instruction::BitCast;
// ptrtoint, inttoptr -> bitcast (ptr -> ptr) if int size is >= ptr size.
if (!SrcIntPtrTy || DstIntPtrTy != SrcIntPtrTy)
return 0;
unsigned PtrSize = SrcIntPtrTy->getScalarSizeInBits();
if (MidSize >= PtrSize)
return Instruction::BitCast;
return 0;
}
case 8: {
// ext, trunc -> bitcast, if the SrcTy and DstTy are same size
// ext, trunc -> ext, if sizeof(SrcTy) < sizeof(DstTy)
// ext, trunc -> trunc, if sizeof(SrcTy) > sizeof(DstTy)
unsigned SrcSize = SrcTy->getScalarSizeInBits();
unsigned DstSize = DstTy->getScalarSizeInBits();
if (SrcSize == DstSize)
return Instruction::BitCast;
else if (SrcSize < DstSize)
return firstOp;
return secondOp;
}
case 9:
// zext, sext -> zext, because sext can't sign extend after zext
return Instruction::ZExt;
case 10:
// fpext followed by ftrunc is allowed if the bit size returned to is
// the same as the original, in which case its just a bitcast
if (SrcTy == DstTy)
return Instruction::BitCast;
return 0; // If the types are not the same we can't eliminate it.
case 11: {
// inttoptr, ptrtoint -> bitcast if SrcSize<=PtrSize and SrcSize==DstSize
if (!MidIntPtrTy)
return 0;
unsigned PtrSize = MidIntPtrTy->getScalarSizeInBits();
unsigned SrcSize = SrcTy->getScalarSizeInBits();
unsigned DstSize = DstTy->getScalarSizeInBits();
if (SrcSize <= PtrSize && SrcSize == DstSize)
return Instruction::BitCast;
return 0;
}
case 12:
// addrspacecast, addrspacecast -> bitcast, if SrcAS == DstAS
// addrspacecast, addrspacecast -> addrspacecast, if SrcAS != DstAS
if (SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace())
return Instruction::AddrSpaceCast;
return Instruction::BitCast;
case 13:
// FIXME: this state can be merged with (1), but the following assert
// is useful to check the correcteness of the sequence due to semantic
// change of bitcast.
assert(
SrcTy->isPtrOrPtrVectorTy() &&
MidTy->isPtrOrPtrVectorTy() &&
DstTy->isPtrOrPtrVectorTy() &&
SrcTy->getPointerAddressSpace() != MidTy->getPointerAddressSpace() &&
MidTy->getPointerAddressSpace() == DstTy->getPointerAddressSpace() &&
"Illegal addrspacecast, bitcast sequence!");
// Allowed, use first cast's opcode
return firstOp;
case 14:
// bitcast, addrspacecast -> addrspacecast if the element type of
// bitcast's source is the same as that of addrspacecast's destination.
if (SrcTy->getScalarType()->getPointerElementType() ==
DstTy->getScalarType()->getPointerElementType())
return Instruction::AddrSpaceCast;
return 0;
case 15:
// FIXME: this state can be merged with (1), but the following assert
// is useful to check the correcteness of the sequence due to semantic
// change of bitcast.
assert(
SrcTy->isIntOrIntVectorTy() &&
MidTy->isPtrOrPtrVectorTy() &&
DstTy->isPtrOrPtrVectorTy() &&
MidTy->getPointerAddressSpace() == DstTy->getPointerAddressSpace() &&
"Illegal inttoptr, bitcast sequence!");
// Allowed, use first cast's opcode
return firstOp;
case 16:
// FIXME: this state can be merged with (2), but the following assert
// is useful to check the correcteness of the sequence due to semantic
// change of bitcast.
assert(
SrcTy->isPtrOrPtrVectorTy() &&
MidTy->isPtrOrPtrVectorTy() &&
DstTy->isIntOrIntVectorTy() &&
SrcTy->getPointerAddressSpace() == MidTy->getPointerAddressSpace() &&
"Illegal bitcast, ptrtoint sequence!");
// Allowed, use second cast's opcode
return secondOp;
case 17:
// (sitofp (zext x)) -> (uitofp x)
return Instruction::UIToFP;
case 99:
// Cast combination can't happen (error in input). This is for all cases
// where the MidTy is not the same for the two cast instructions.
llvm_unreachable("Invalid Cast Combination");
default:
llvm_unreachable("Error in CastResults table!!!");
}
}
CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
const Twine &Name, Instruction *InsertBefore) {
assert(castIsValid(op, S, Ty) && "Invalid cast!");
// Construct and return the appropriate CastInst subclass
switch (op) {
case Trunc: return new TruncInst (S, Ty, Name, InsertBefore);
case ZExt: return new ZExtInst (S, Ty, Name, InsertBefore);
case SExt: return new SExtInst (S, Ty, Name, InsertBefore);
case FPTrunc: return new FPTruncInst (S, Ty, Name, InsertBefore);
case FPExt: return new FPExtInst (S, Ty, Name, InsertBefore);
case UIToFP: return new UIToFPInst (S, Ty, Name, InsertBefore);
case SIToFP: return new SIToFPInst (S, Ty, Name, InsertBefore);
case FPToUI: return new FPToUIInst (S, Ty, Name, InsertBefore);
case FPToSI: return new FPToSIInst (S, Ty, Name, InsertBefore);
case PtrToInt: return new PtrToIntInst (S, Ty, Name, InsertBefore);
case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertBefore);
case BitCast: return new BitCastInst (S, Ty, Name, InsertBefore);
case AddrSpaceCast: return new AddrSpaceCastInst (S, Ty, Name, InsertBefore);
default: llvm_unreachable("Invalid opcode provided");
}
}
CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
const Twine &Name, BasicBlock *InsertAtEnd) {
assert(castIsValid(op, S, Ty) && "Invalid cast!");
// Construct and return the appropriate CastInst subclass
switch (op) {
case Trunc: return new TruncInst (S, Ty, Name, InsertAtEnd);
case ZExt: return new ZExtInst (S, Ty, Name, InsertAtEnd);
case SExt: return new SExtInst (S, Ty, Name, InsertAtEnd);
case FPTrunc: return new FPTruncInst (S, Ty, Name, InsertAtEnd);
case FPExt: return new FPExtInst (S, Ty, Name, InsertAtEnd);
case UIToFP: return new UIToFPInst (S, Ty, Name, InsertAtEnd);
case SIToFP: return new SIToFPInst (S, Ty, Name, InsertAtEnd);
case FPToUI: return new FPToUIInst (S, Ty, Name, InsertAtEnd);
case FPToSI: return new FPToSIInst (S, Ty, Name, InsertAtEnd);
case PtrToInt: return new PtrToIntInst (S, Ty, Name, InsertAtEnd);
case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertAtEnd);
case BitCast: return new BitCastInst (S, Ty, Name, InsertAtEnd);
case AddrSpaceCast: return new AddrSpaceCastInst (S, Ty, Name, InsertAtEnd);
default: llvm_unreachable("Invalid opcode provided");
}
}
CastInst *CastInst::CreateZExtOrBitCast(Value *S, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
return Create(Instruction::ZExt, S, Ty, Name, InsertBefore);
}
CastInst *CastInst::CreateZExtOrBitCast(Value *S, Type *Ty,
const Twine &Name,
BasicBlock *InsertAtEnd) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
return Create(Instruction::ZExt, S, Ty, Name, InsertAtEnd);
}
CastInst *CastInst::CreateSExtOrBitCast(Value *S, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
return Create(Instruction::SExt, S, Ty, Name, InsertBefore);
}
CastInst *CastInst::CreateSExtOrBitCast(Value *S, Type *Ty,
const Twine &Name,
BasicBlock *InsertAtEnd) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
return Create(Instruction::SExt, S, Ty, Name, InsertAtEnd);
}
CastInst *CastInst::CreateTruncOrBitCast(Value *S, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
return Create(Instruction::Trunc, S, Ty, Name, InsertBefore);
}
CastInst *CastInst::CreateTruncOrBitCast(Value *S, Type *Ty,
const Twine &Name,
BasicBlock *InsertAtEnd) {
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
return Create(Instruction::Trunc, S, Ty, Name, InsertAtEnd);
}
CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty,
const Twine &Name,
BasicBlock *InsertAtEnd) {
assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast");
assert((Ty->isIntOrIntVectorTy() || Ty->isPtrOrPtrVectorTy()) &&
"Invalid cast");
assert(Ty->isVectorTy() == S->getType()->isVectorTy() && "Invalid cast");
assert((!Ty->isVectorTy() ||
Ty->getVectorNumElements() == S->getType()->getVectorNumElements()) &&
"Invalid cast");
if (Ty->isIntOrIntVectorTy())
return Create(Instruction::PtrToInt, S, Ty, Name, InsertAtEnd);
return CreatePointerBitCastOrAddrSpaceCast(S, Ty, Name, InsertAtEnd);
}
/// @brief Create a BitCast or a PtrToInt cast instruction
CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast");
assert((Ty->isIntOrIntVectorTy() || Ty->isPtrOrPtrVectorTy()) &&
"Invalid cast");
assert(Ty->isVectorTy() == S->getType()->isVectorTy() && "Invalid cast");
assert((!Ty->isVectorTy() ||
Ty->getVectorNumElements() == S->getType()->getVectorNumElements()) &&
"Invalid cast");
if (Ty->isIntOrIntVectorTy())
return Create(Instruction::PtrToInt, S, Ty, Name, InsertBefore);
return CreatePointerBitCastOrAddrSpaceCast(S, Ty, Name, InsertBefore);
}
CastInst *CastInst::CreatePointerBitCastOrAddrSpaceCast(
Value *S, Type *Ty,
const Twine &Name,
BasicBlock *InsertAtEnd) {
assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast");
assert(Ty->isPtrOrPtrVectorTy() && "Invalid cast");
if (S->getType()->getPointerAddressSpace() != Ty->getPointerAddressSpace())
return Create(Instruction::AddrSpaceCast, S, Ty, Name, InsertAtEnd);
return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
}
CastInst *CastInst::CreatePointerBitCastOrAddrSpaceCast(
Value *S, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast");
assert(Ty->isPtrOrPtrVectorTy() && "Invalid cast");
if (S->getType()->getPointerAddressSpace() != Ty->getPointerAddressSpace())
return Create(Instruction::AddrSpaceCast, S, Ty, Name, InsertBefore);
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
}
CastInst *CastInst::CreateBitOrPointerCast(Value *S, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
if (S->getType()->isPointerTy() && Ty->isIntegerTy())
return Create(Instruction::PtrToInt, S, Ty, Name, InsertBefore);
if (S->getType()->isIntegerTy() && Ty->isPointerTy())
return Create(Instruction::IntToPtr, S, Ty, Name, InsertBefore);
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
}
CastInst *CastInst::CreateIntegerCast(Value *C, Type *Ty,
bool isSigned, const Twine &Name,
Instruction *InsertBefore) {
assert(C->getType()->isIntOrIntVectorTy() && Ty->isIntOrIntVectorTy() &&
"Invalid integer cast");
unsigned SrcBits = C->getType()->getScalarSizeInBits();
unsigned DstBits = Ty->getScalarSizeInBits();
Instruction::CastOps opcode =
(SrcBits == DstBits ? Instruction::BitCast :
(SrcBits > DstBits ? Instruction::Trunc :
(isSigned ? Instruction::SExt : Instruction::ZExt)));
return Create(opcode, C, Ty, Name, InsertBefore);
}
CastInst *CastInst::CreateIntegerCast(Value *C, Type *Ty,
bool isSigned, const Twine &Name,
BasicBlock *InsertAtEnd) {
assert(C->getType()->isIntOrIntVectorTy() && Ty->isIntOrIntVectorTy() &&
"Invalid cast");
unsigned SrcBits = C->getType()->getScalarSizeInBits();
unsigned DstBits = Ty->getScalarSizeInBits();
Instruction::CastOps opcode =
(SrcBits == DstBits ? Instruction::BitCast :
(SrcBits > DstBits ? Instruction::Trunc :
(isSigned ? Instruction::SExt : Instruction::ZExt)));
return Create(opcode, C, Ty, Name, InsertAtEnd);
}
CastInst *CastInst::CreateFPCast(Value *C, Type *Ty,
const Twine &Name,
Instruction *InsertBefore) {
assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() &&
"Invalid cast");
unsigned SrcBits = C->getType()->getScalarSizeInBits();
unsigned DstBits = Ty->getScalarSizeInBits();
Instruction::CastOps opcode =
(SrcBits == DstBits ? Instruction::BitCast :
(SrcBits > DstBits ? Instruction::FPTrunc : Instruction::FPExt));
return Create(opcode, C, Ty, Name, InsertBefore);
}
CastInst *CastInst::CreateFPCast(Value *C, Type *Ty,
const Twine &Name,
BasicBlock *InsertAtEnd) {
assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() &&
"Invalid cast");
unsigned SrcBits = C->getType()->getScalarSizeInBits();
unsigned DstBits = Ty->getScalarSizeInBits();
Instruction::CastOps opcode =
(SrcBits == DstBits ? Instruction::BitCast :
(SrcBits > DstBits ? Instruction::FPTrunc : Instruction::FPExt));
return Create(opcode, C, Ty, Name, InsertAtEnd);
}
// Check whether it is valid to call getCastOpcode for these types.
// This routine must be kept in sync with getCastOpcode.
bool CastInst::isCastable(Type *SrcTy, Type *DestTy) {
if (!SrcTy->isFirstClassType() || !DestTy->isFirstClassType())
return false;
if (SrcTy == DestTy)
return true;
if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy))
if (VectorType *DestVecTy = dyn_cast<VectorType>(DestTy))
if (SrcVecTy->getNumElements() == DestVecTy->getNumElements()) {
// An element by element cast. Valid if casting the elements is valid.
SrcTy = SrcVecTy->getElementType();
DestTy = DestVecTy->getElementType();
}
// Get the bit sizes, we'll need these
unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr
unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr
// Run through the possibilities ...
if (DestTy->isIntegerTy()) { // Casting to integral
if (SrcTy->isIntegerTy()) // Casting from integral
return true;
if (SrcTy->isFloatingPointTy()) // Casting from floating pt
return true;
if (SrcTy->isVectorTy()) // Casting from vector
return DestBits == SrcBits;
// Casting from something else
return SrcTy->isPointerTy();
}
if (DestTy->isFloatingPointTy()) { // Casting to floating pt
if (SrcTy->isIntegerTy()) // Casting from integral
return true;
if (SrcTy->isFloatingPointTy()) // Casting from floating pt
return true;
if (SrcTy->isVectorTy()) // Casting from vector
return DestBits == SrcBits;
// Casting from something else
return false;
}
if (DestTy->isVectorTy()) // Casting to vector
return DestBits == SrcBits;
if (DestTy->isPointerTy()) { // Casting to pointer
if (SrcTy->isPointerTy()) // Casting from pointer
return true;
return SrcTy->isIntegerTy(); // Casting from integral
}
if (DestTy->isX86_MMXTy()) {
if (SrcTy->isVectorTy())
return DestBits == SrcBits; // 64-bit vector to MMX
return false;
} // Casting to something else
return false;
}
bool CastInst::isBitCastable(Type *SrcTy, Type *DestTy) {
if (!SrcTy->isFirstClassType() || !DestTy->isFirstClassType())
return false;
if (SrcTy == DestTy)
return true;
if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy)) {
if (VectorType *DestVecTy = dyn_cast<VectorType>(DestTy)) {
if (SrcVecTy->getNumElements() == DestVecTy->getNumElements()) {
// An element by element cast. Valid if casting the elements is valid.
SrcTy = SrcVecTy->getElementType();
DestTy = DestVecTy->getElementType();
}
}
}
if (PointerType *DestPtrTy = dyn_cast<PointerType>(DestTy)) {
if (PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy)) {
return SrcPtrTy->getAddressSpace() == DestPtrTy->getAddressSpace();
}
}
unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr
unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr
// Could still have vectors of pointers if the number of elements doesn't
// match
if (SrcBits == 0 || DestBits == 0)
return false;
if (SrcBits != DestBits)
return false;
if (DestTy->isX86_MMXTy() || SrcTy->isX86_MMXTy())
return false;
return true;
}
bool CastInst::isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy,
const DataLayout &DL) {
if (auto *PtrTy = dyn_cast<PointerType>(SrcTy))
if (auto *IntTy = dyn_cast<IntegerType>(DestTy))
return IntTy->getBitWidth() == DL.getPointerTypeSizeInBits(PtrTy);
if (auto *PtrTy = dyn_cast<PointerType>(DestTy))
if (auto *IntTy = dyn_cast<IntegerType>(SrcTy))
return IntTy->getBitWidth() == DL.getPointerTypeSizeInBits(PtrTy);
return isBitCastable(SrcTy, DestTy);
}
// Provide a way to get a "cast" where the cast opcode is inferred from the
// types and size of the operand. This, basically, is a parallel of the
// logic in the castIsValid function below. This axiom should hold:
// castIsValid( getCastOpcode(Val, Ty), Val, Ty)
// should not assert in castIsValid. In other words, this produces a "correct"
// casting opcode for the arguments passed to it.
// This routine must be kept in sync with isCastable.
Instruction::CastOps
CastInst::getCastOpcode(
const Value *Src, bool SrcIsSigned, Type *DestTy, bool DestIsSigned) {
Type *SrcTy = Src->getType();
assert(SrcTy->isFirstClassType() && DestTy->isFirstClassType() &&
"Only first class types are castable!");
if (SrcTy == DestTy)
return BitCast;
// FIXME: Check address space sizes here
if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy))
if (VectorType *DestVecTy = dyn_cast<VectorType>(DestTy))
if (SrcVecTy->getNumElements() == DestVecTy->getNumElements()) {
// An element by element cast. Find the appropriate opcode based on the
// element types.
SrcTy = SrcVecTy->getElementType();
DestTy = DestVecTy->getElementType();
}
// Get the bit sizes, we'll need these
unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr
unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr
// Run through the possibilities ...
if (DestTy->isIntegerTy()) { // Casting to integral
if (SrcTy->isIntegerTy()) { // Casting from integral
if (DestBits < SrcBits)
return Trunc; // int -> smaller int
else if (DestBits > SrcBits) { // its an extension
if (SrcIsSigned)
return SExt; // signed -> SEXT
else
return ZExt; // unsigned -> ZEXT
} else {
return BitCast; // Same size, No-op cast
}
} else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt
if (DestIsSigned)
return FPToSI; // FP -> sint
else
return FPToUI; // FP -> uint
} else if (SrcTy->isVectorTy()) {
assert(DestBits == SrcBits &&
"Casting vector to integer of different width");
return BitCast; // Same size, no-op cast
} else {
assert(SrcTy->isPointerTy() &&
"Casting from a value that is not first-class type");
return PtrToInt; // ptr -> int
}
} else if (DestTy->isFloatingPointTy()) { // Casting to floating pt
if (SrcTy->isIntegerTy()) { // Casting from integral
if (SrcIsSigned)
return SIToFP; // sint -> FP
else
return UIToFP; // uint -> FP
} else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt
if (DestBits < SrcBits) {
return FPTrunc; // FP -> smaller FP
} else if (DestBits > SrcBits) {
return FPExt; // FP -> larger FP
} else {
return BitCast; // same size, no-op cast
}
} else if (SrcTy->isVectorTy()) {
assert(DestBits == SrcBits &&
"Casting vector to floating point of different width");
return BitCast; // same size, no-op cast
}
llvm_unreachable("Casting pointer or non-first class to float");
} else if (DestTy->isVectorTy()) {
assert(DestBits == SrcBits &&
"Illegal cast to vector (wrong type or size)");
return BitCast;
} else if (DestTy->isPointerTy()) {
if (SrcTy->isPointerTy()) {
if (DestTy->getPointerAddressSpace() != SrcTy->getPointerAddressSpace())
return AddrSpaceCast;
return BitCast; // ptr -> ptr
} else if (SrcTy->isIntegerTy()) {
return IntToPtr; // int -> ptr
}
llvm_unreachable("Casting pointer to other than pointer or int");
} else if (DestTy->isX86_MMXTy()) {
if (SrcTy->isVectorTy()) {
assert(DestBits == SrcBits && "Casting vector of wrong width to X86_MMX");
return BitCast; // 64-bit vector to MMX
}
llvm_unreachable("Illegal cast to X86_MMX");
}
llvm_unreachable("Casting to type that is not first-class");
}
//===----------------------------------------------------------------------===//
// CastInst SubClass Constructors
//===----------------------------------------------------------------------===//
/// Check that the construction parameters for a CastInst are correct. This
/// could be broken out into the separate constructors but it is useful to have
/// it in one place and to eliminate the redundant code for getting the sizes
/// of the types involved.
bool
CastInst::castIsValid(Instruction::CastOps op, Value *S, Type *DstTy) {
// Check for type sanity on the arguments
Type *SrcTy = S->getType();
if (!SrcTy->isFirstClassType() || !DstTy->isFirstClassType() ||
SrcTy->isAggregateType() || DstTy->isAggregateType())
return false;
// Get the size of the types in bits, we'll need this later
unsigned SrcBitSize = SrcTy->getScalarSizeInBits();
unsigned DstBitSize = DstTy->getScalarSizeInBits();
// If these are vector types, get the lengths of the vectors (using zero for
// scalar types means that checking that vector lengths match also checks that
// scalars are not being converted to vectors or vectors to scalars).
unsigned SrcLength = SrcTy->isVectorTy() ?
cast<VectorType>(SrcTy)->getNumElements() : 0;
unsigned DstLength = DstTy->isVectorTy() ?
cast<VectorType>(DstTy)->getNumElements() : 0;
// Switch on the opcode provided
switch (op) {
default: return false; // This is an input error
case Instruction::Trunc:
return SrcTy->isIntOrIntVectorTy() && DstTy->isIntOrIntVectorTy() &&
SrcLength == DstLength && SrcBitSize > DstBitSize;
case Instruction::ZExt:
return SrcTy->isIntOrIntVectorTy() && DstTy->isIntOrIntVectorTy() &&
SrcLength == DstLength && SrcBitSize < DstBitSize;
case Instruction::SExt:
return SrcTy->isIntOrIntVectorTy() && DstTy->isIntOrIntVectorTy() &&
SrcLength == DstLength && SrcBitSize < DstBitSize;
case Instruction::FPTrunc:
return SrcTy->isFPOrFPVectorTy() && DstTy->isFPOrFPVectorTy() &&
SrcLength == DstLength && SrcBitSize > DstBitSize;
case Instruction::FPExt:
return SrcTy->isFPOrFPVectorTy() && DstTy->isFPOrFPVectorTy() &&
SrcLength == DstLength && SrcBitSize < DstBitSize;
case Instruction::UIToFP:
case Instruction::SIToFP:
return SrcTy->isIntOrIntVectorTy() && DstTy->isFPOrFPVectorTy() &&
SrcLength == DstLength;
case Instruction::FPToUI:
case Instruction::FPToSI:
return SrcTy->isFPOrFPVectorTy() && DstTy->isIntOrIntVectorTy() &&
SrcLength == DstLength;
case Instruction::PtrToInt:
if (isa<VectorType>(SrcTy) != isa<VectorType>(DstTy))
return false;
if (VectorType *VT = dyn_cast<VectorType>(SrcTy))
if (VT->getNumElements() != cast<VectorType>(DstTy)->getNumElements())
return false;
return SrcTy->isPtrOrPtrVectorTy() && DstTy->isIntOrIntVectorTy();
case Instruction::IntToPtr:
if (isa<VectorType>(SrcTy) != isa<VectorType>(DstTy))
return false;
if (VectorType *VT = dyn_cast<VectorType>(SrcTy))
if (VT->getNumElements() != cast<VectorType>(DstTy)->getNumElements())
return false;
return SrcTy->isIntOrIntVectorTy() && DstTy->isPtrOrPtrVectorTy();
case Instruction::BitCast: {
PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy->getScalarType());
PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy->getScalarType());
// BitCast implies a no-op cast of type only. No bits change.
// However, you can't cast pointers to anything but pointers.
if (!SrcPtrTy != !DstPtrTy)
return false;
// For non-pointer cases, the cast is okay if the source and destination bit
// widths are identical.
if (!SrcPtrTy)
return SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits();
// If both are pointers then the address spaces must match.
if (SrcPtrTy->getAddressSpace() != DstPtrTy->getAddressSpace())
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;
}
return true;
}
case Instruction::AddrSpaceCast: {
PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy->getScalarType());
if (!SrcPtrTy)
return false;
PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy->getScalarType());
if (!DstPtrTy)
return false;
if (SrcPtrTy->getAddressSpace() == DstPtrTy->getAddressSpace())
return false;
if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy)) {
if (VectorType *DstVecTy = dyn_cast<VectorType>(DstTy))
return (SrcVecTy->getNumElements() == DstVecTy->getNumElements());
return false;
}
return true;
}
}
}
TruncInst::TruncInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, Trunc, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal Trunc");
}
TruncInst::TruncInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, Trunc, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal Trunc");
}
ZExtInst::ZExtInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, ZExt, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal ZExt");
}
ZExtInst::ZExtInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, ZExt, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal ZExt");
}
SExtInst::SExtInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, SExt, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SExt");
}
SExtInst::SExtInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, SExt, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SExt");
}
FPTruncInst::FPTruncInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, FPTrunc, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPTrunc");
}
FPTruncInst::FPTruncInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPTrunc, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPTrunc");
}
FPExtInst::FPExtInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, FPExt, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPExt");
}
FPExtInst::FPExtInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPExt, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPExt");
}
UIToFPInst::UIToFPInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, UIToFP, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal UIToFP");
}
UIToFPInst::UIToFPInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, UIToFP, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal UIToFP");
}
SIToFPInst::SIToFPInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, SIToFP, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SIToFP");
}
SIToFPInst::SIToFPInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, SIToFP, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SIToFP");
}
FPToUIInst::FPToUIInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, FPToUI, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToUI");
}
FPToUIInst::FPToUIInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPToUI, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToUI");
}
FPToSIInst::FPToSIInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, FPToSI, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToSI");
}
FPToSIInst::FPToSIInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, FPToSI, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToSI");
}
PtrToIntInst::PtrToIntInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, PtrToInt, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal PtrToInt");
}
PtrToIntInst::PtrToIntInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, PtrToInt, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal PtrToInt");
}
IntToPtrInst::IntToPtrInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, IntToPtr, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal IntToPtr");
}
IntToPtrInst::IntToPtrInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, IntToPtr, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal IntToPtr");
}
BitCastInst::BitCastInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, BitCast, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal BitCast");
}
BitCastInst::BitCastInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, BitCast, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal BitCast");
}
AddrSpaceCastInst::AddrSpaceCastInst(
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
) : CastInst(Ty, AddrSpaceCast, S, Name, InsertBefore) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal AddrSpaceCast");
}
AddrSpaceCastInst::AddrSpaceCastInst(
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
) : CastInst(Ty, AddrSpaceCast, S, Name, InsertAtEnd) {
assert(castIsValid(getOpcode(), S, Ty) && "Illegal AddrSpaceCast");
}
//===----------------------------------------------------------------------===//
// CmpInst Classes
//===----------------------------------------------------------------------===//
CmpInst::CmpInst(Type *ty, OtherOps op, Predicate predicate, Value *LHS,
Value *RHS, const Twine &Name, Instruction *InsertBefore)
: Instruction(ty, op,
OperandTraits<CmpInst>::op_begin(this),
OperandTraits<CmpInst>::operands(this),
InsertBefore) {
Op<0>() = LHS;
Op<1>() = RHS;
setPredicate((Predicate)predicate);
setName(Name);
}
CmpInst::CmpInst(Type *ty, OtherOps op, Predicate predicate, Value *LHS,
Value *RHS, const Twine &Name, BasicBlock *InsertAtEnd)
: Instruction(ty, op,
OperandTraits<CmpInst>::op_begin(this),
OperandTraits<CmpInst>::operands(this),
InsertAtEnd) {
Op<0>() = LHS;
Op<1>() = RHS;
setPredicate((Predicate)predicate);
setName(Name);
}
CmpInst *
CmpInst::Create(OtherOps Op, Predicate predicate, Value *S1, Value *S2,
const Twine &Name, Instruction *InsertBefore) {
if (Op == Instruction::ICmp) {
if (InsertBefore)
return new ICmpInst(InsertBefore, CmpInst::Predicate(predicate),
S1, S2, Name);
else
return new ICmpInst(CmpInst::Predicate(predicate),
S1, S2, Name);
}
if (InsertBefore)
return new FCmpInst(InsertBefore, CmpInst::Predicate(predicate),
S1, S2, Name);
else
return new FCmpInst(CmpInst::Predicate(predicate),
S1, S2, Name);
}
CmpInst *
CmpInst::Create(OtherOps Op, Predicate predicate, Value *S1, Value *S2,
const Twine &Name, BasicBlock *InsertAtEnd) {
if (Op == Instruction::ICmp) {
return new ICmpInst(*InsertAtEnd, CmpInst::Predicate(predicate),
S1, S2, Name);
}
return new FCmpInst(*InsertAtEnd, CmpInst::Predicate(predicate),
S1, S2, Name);
}
void CmpInst::swapOperands() {
if (ICmpInst *IC = dyn_cast<ICmpInst>(this))
IC->swapOperands();
else
cast<FCmpInst>(this)->swapOperands();
}
bool CmpInst::isCommutative() const {
if (const ICmpInst *IC = dyn_cast<ICmpInst>(this))
return IC->isCommutative();
return cast<FCmpInst>(this)->isCommutative();
}
bool CmpInst::isEquality() const {
if (const ICmpInst *IC = dyn_cast<ICmpInst>(this))
return IC->isEquality();
return cast<FCmpInst>(this)->isEquality();
}
CmpInst::Predicate CmpInst::getInversePredicate(Predicate pred) {
switch (pred) {
default: llvm_unreachable("Unknown cmp predicate!");
case ICMP_EQ: return ICMP_NE;
case ICMP_NE: return ICMP_EQ;
case ICMP_UGT: return ICMP_ULE;
case ICMP_ULT: return ICMP_UGE;
case ICMP_UGE: return ICMP_ULT;
case ICMP_ULE: return ICMP_UGT;
case ICMP_SGT: return ICMP_SLE;
case ICMP_SLT: return ICMP_SGE;
case ICMP_SGE: return ICMP_SLT;
case ICMP_SLE: return ICMP_SGT;
case FCMP_OEQ: return FCMP_UNE;
case FCMP_ONE: return FCMP_UEQ;
case FCMP_OGT: return FCMP_ULE;
case FCMP_OLT: return FCMP_UGE;
case FCMP_OGE: return FCMP_ULT;
case FCMP_OLE: return FCMP_UGT;
case FCMP_UEQ: return FCMP_ONE;
case FCMP_UNE: return FCMP_OEQ;
case FCMP_UGT: return FCMP_OLE;
case FCMP_ULT: return FCMP_OGE;
case FCMP_UGE: return FCMP_OLT;
case FCMP_ULE: return FCMP_OGT;
case FCMP_ORD: return FCMP_UNO;
case FCMP_UNO: return FCMP_ORD;
case FCMP_TRUE: return FCMP_FALSE;
case FCMP_FALSE: return FCMP_TRUE;
}
}
StringRef CmpInst::getPredicateName(Predicate Pred) {
switch (Pred) {
default: return "unknown";
case FCmpInst::FCMP_FALSE: return "false";
case FCmpInst::FCMP_OEQ: return "oeq";
case FCmpInst::FCMP_OGT: return "ogt";
case FCmpInst::FCMP_OGE: return "oge";
case FCmpInst::FCMP_OLT: return "olt";
case FCmpInst::FCMP_OLE: return "ole";
case FCmpInst::FCMP_ONE: return "one";
case FCmpInst::FCMP_ORD: return "ord";
case FCmpInst::FCMP_UNO: return "uno";
case FCmpInst::FCMP_UEQ: return "ueq";
case FCmpInst::FCMP_UGT: return "ugt";
case FCmpInst::FCMP_UGE: return "uge";
case FCmpInst::FCMP_ULT: return "ult";
case FCmpInst::FCMP_ULE: return "ule";
case FCmpInst::FCMP_UNE: return "une";
case FCmpInst::FCMP_TRUE: return "true";
case ICmpInst::ICMP_EQ: return "eq";
case ICmpInst::ICMP_NE: return "ne";
case ICmpInst::ICMP_SGT: return "sgt";
case ICmpInst::ICMP_SGE: return "sge";
case ICmpInst::ICMP_SLT: return "slt";
case ICmpInst::ICMP_SLE: return "sle";
case ICmpInst::ICMP_UGT: return "ugt";
case ICmpInst::ICMP_UGE: return "uge";
case ICmpInst::ICMP_ULT: return "ult";
case ICmpInst::ICMP_ULE: return "ule";
}
}
ICmpInst::Predicate ICmpInst::getSignedPredicate(Predicate pred) {
switch (pred) {
default: llvm_unreachable("Unknown icmp predicate!");
case ICMP_EQ: case ICMP_NE:
case ICMP_SGT: case ICMP_SLT: case ICMP_SGE: case ICMP_SLE:
return pred;
case ICMP_UGT: return ICMP_SGT;
case ICMP_ULT: return ICMP_SLT;
case ICMP_UGE: return ICMP_SGE;
case ICMP_ULE: return ICMP_SLE;
}
}
ICmpInst::Predicate ICmpInst::getUnsignedPredicate(Predicate pred) {
switch (pred) {
default: llvm_unreachable("Unknown icmp predicate!");
case ICMP_EQ: case ICMP_NE:
case ICMP_UGT: case ICMP_ULT: case ICMP_UGE: case ICMP_ULE:
return pred;
case ICMP_SGT: return ICMP_UGT;
case ICMP_SLT: return ICMP_ULT;
case ICMP_SGE: return ICMP_UGE;
case ICMP_SLE: return ICMP_ULE;
}
}
CmpInst::Predicate CmpInst::getSwappedPredicate(Predicate pred) {
switch (pred) {
default: llvm_unreachable("Unknown cmp predicate!");
case ICMP_EQ: case ICMP_NE:
return pred;
case ICMP_SGT: return ICMP_SLT;
case ICMP_SLT: return ICMP_SGT;
case ICMP_SGE: return ICMP_SLE;
case ICMP_SLE: return ICMP_SGE;
case ICMP_UGT: return ICMP_ULT;
case ICMP_ULT: return ICMP_UGT;
case ICMP_UGE: return ICMP_ULE;
case ICMP_ULE: return ICMP_UGE;
case FCMP_FALSE: case FCMP_TRUE:
case FCMP_OEQ: case FCMP_ONE:
case FCMP_UEQ: case FCMP_UNE:
case FCMP_ORD: case FCMP_UNO:
return pred;
case FCMP_OGT: return FCMP_OLT;
case FCMP_OLT: return FCMP_OGT;
case FCMP_OGE: return FCMP_OLE;
case FCMP_OLE: return FCMP_OGE;
case FCMP_UGT: return FCMP_ULT;
case FCMP_ULT: return FCMP_UGT;
case FCMP_UGE: return FCMP_ULE;
case FCMP_ULE: return FCMP_UGE;
}
}
CmpInst::Predicate CmpInst::getSignedPredicate(Predicate pred) {
assert(CmpInst::isUnsigned(pred) && "Call only with signed predicates!");
switch (pred) {
default:
llvm_unreachable("Unknown predicate!");
case CmpInst::ICMP_ULT:
return CmpInst::ICMP_SLT;
case CmpInst::ICMP_ULE:
return CmpInst::ICMP_SLE;
case CmpInst::ICMP_UGT:
return CmpInst::ICMP_SGT;
case CmpInst::ICMP_UGE:
return CmpInst::ICMP_SGE;
}
}
bool CmpInst::isUnsigned(Predicate predicate) {
switch (predicate) {
default: return false;
case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_ULE: case ICmpInst::ICMP_UGT:
case ICmpInst::ICMP_UGE: return true;
}
}
bool CmpInst::isSigned(Predicate predicate) {
switch (predicate) {
default: return false;
case ICmpInst::ICMP_SLT: case ICmpInst::ICMP_SLE: case ICmpInst::ICMP_SGT:
case ICmpInst::ICMP_SGE: return true;
}
}
bool CmpInst::isOrdered(Predicate predicate) {
switch (predicate) {
default: return false;
case FCmpInst::FCMP_OEQ: case FCmpInst::FCMP_ONE: case FCmpInst::FCMP_OGT:
case FCmpInst::FCMP_OLT: case FCmpInst::FCMP_OGE: case FCmpInst::FCMP_OLE:
case FCmpInst::FCMP_ORD: return true;
}
}
bool CmpInst::isUnordered(Predicate predicate) {
switch (predicate) {
default: return false;
case FCmpInst::FCMP_UEQ: case FCmpInst::FCMP_UNE: case FCmpInst::FCMP_UGT:
case FCmpInst::FCMP_ULT: case FCmpInst::FCMP_UGE: case FCmpInst::FCMP_ULE:
case FCmpInst::FCMP_UNO: return true;
}
}
bool CmpInst::isTrueWhenEqual(Predicate predicate) {
switch(predicate) {
default: return false;
case ICMP_EQ: case ICMP_UGE: case ICMP_ULE: case ICMP_SGE: case ICMP_SLE:
case FCMP_TRUE: case FCMP_UEQ: case FCMP_UGE: case FCMP_ULE: return true;
}
}
bool CmpInst::isFalseWhenEqual(Predicate predicate) {
switch(predicate) {
case ICMP_NE: case ICMP_UGT: case ICMP_ULT: case ICMP_SGT: case ICMP_SLT:
case FCMP_FALSE: case FCMP_ONE: case FCMP_OGT: case FCMP_OLT: return true;
default: return false;
}
}
bool CmpInst::isImpliedTrueByMatchingCmp(Predicate Pred1, Predicate Pred2) {
// If the predicates match, then we know the first condition implies the
// second is true.
if (Pred1 == Pred2)
return true;
switch (Pred1) {
default:
break;
case ICMP_EQ:
// A == B implies A >=u B, A <=u B, A >=s B, and A <=s B are true.
return Pred2 == ICMP_UGE || Pred2 == ICMP_ULE || Pred2 == ICMP_SGE ||
Pred2 == ICMP_SLE;
case ICMP_UGT: // A >u B implies A != B and A >=u B are true.
return Pred2 == ICMP_NE || Pred2 == ICMP_UGE;
case ICMP_ULT: // A <u B implies A != B and A <=u B are true.
return Pred2 == ICMP_NE || Pred2 == ICMP_ULE;
case ICMP_SGT: // A >s B implies A != B and A >=s B are true.
return Pred2 == ICMP_NE || Pred2 == ICMP_SGE;
case ICMP_SLT: // A <s B implies A != B and A <=s B are true.
return Pred2 == ICMP_NE || Pred2 == ICMP_SLE;
}
return false;
}
bool CmpInst::isImpliedFalseByMatchingCmp(Predicate Pred1, Predicate Pred2) {
return isImpliedTrueByMatchingCmp(Pred1, getInversePredicate(Pred2));
}
//===----------------------------------------------------------------------===//
// SwitchInst Implementation
//===----------------------------------------------------------------------===//
void SwitchInst::init(Value *Value, BasicBlock *Default, unsigned NumReserved) {
assert(Value && Default && NumReserved);
ReservedSpace = NumReserved;
setNumHungOffUseOperands(2);
allocHungoffUses(ReservedSpace);
Op<0>() = Value;
Op<1>() = Default;
}
/// SwitchInst ctor - Create a new switch instruction, specifying a value to
/// switch on and a default destination. The number of additional cases can
/// be specified here to make memory allocation more efficient. This
/// 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) {
init(Value, Default, 2+NumCases*2);
}
/// SwitchInst ctor - Create a new switch instruction, specifying a value to
/// switch on and a default destination. The number of additional cases can
/// be specified here to make memory allocation more efficient. This
/// 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) {
init(Value, Default, 2+NumCases*2);
}
SwitchInst::SwitchInst(const SwitchInst &SI)
: TerminatorInst(SI.getType(), Instruction::Switch, nullptr, 0) {
init(SI.getCondition(), SI.getDefaultDest(), SI.getNumOperands());
setNumHungOffUseOperands(SI.getNumOperands());
Use *OL = getOperandList();
const Use *InOL = SI.getOperandList();
for (unsigned i = 2, E = SI.getNumOperands(); i != E; i += 2) {
OL[i] = InOL[i];
OL[i+1] = InOL[i+1];
}
SubclassOptionalData = SI.SubclassOptionalData;
}
/// addCase - Add an entry to the switch instruction...
///
void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {
unsigned NewCaseIdx = getNumCases();
unsigned OpNo = getNumOperands();
if (OpNo+2 > ReservedSpace)
growOperands(); // Get more space!
// Initialize some new operands.
assert(OpNo+1 < ReservedSpace && "Growing didn't work!");
setNumHungOffUseOperands(OpNo+2);
CaseHandle Case(this, NewCaseIdx);
Case.setValue(OnVal);
Case.setSuccessor(Dest);
}
/// removeCase - This method removes the specified case and its successor
/// from the switch instruction.
SwitchInst::CaseIt SwitchInst::removeCase(CaseIt I) {
unsigned idx = I->getCaseIndex();
assert(2 + idx*2 < getNumOperands() && "Case index out of range!!!");
unsigned NumOps = getNumOperands();
Use *OL = getOperandList();
// Overwrite this case with the end of the list.
if (2 + (idx + 1) * 2 != NumOps) {
OL[2 + idx * 2] = OL[NumOps - 2];
OL[2 + idx * 2 + 1] = OL[NumOps - 1];
}
// Nuke the last value.
OL[NumOps-2].set(nullptr);
OL[NumOps-2+1].set(nullptr);
setNumHungOffUseOperands(NumOps-2);
return CaseIt(this, idx);
}
/// growOperands - grow operands - This grows the operand list in response
/// to a push_back style of operation. This grows the number of ops by 3 times.
///
void SwitchInst::growOperands() {
unsigned e = getNumOperands();
unsigned NumOps = e*3;
ReservedSpace = NumOps;
growHungoffUses(ReservedSpace);
}
//===----------------------------------------------------------------------===//
// IndirectBrInst Implementation
//===----------------------------------------------------------------------===//
void IndirectBrInst::init(Value *Address, unsigned NumDests) {
assert(Address && Address->getType()->isPointerTy() &&
"Address of indirectbr must be a pointer");
ReservedSpace = 1+NumDests;
setNumHungOffUseOperands(1);
allocHungoffUses(ReservedSpace);
Op<0>() = Address;
}
/// growOperands - grow operands - This grows the operand list in response
/// to a push_back style of operation. This grows the number of ops by 2 times.
///
void IndirectBrInst::growOperands() {
unsigned e = getNumOperands();
unsigned NumOps = e*2;
ReservedSpace = NumOps;
growHungoffUses(ReservedSpace);
}
IndirectBrInst::IndirectBrInst(Value *Address, unsigned NumCases,
Instruction *InsertBefore)
: TerminatorInst(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) {
init(Address, NumCases);
}
IndirectBrInst::IndirectBrInst(const IndirectBrInst &IBI)
: TerminatorInst(Type::getVoidTy(IBI.getContext()), Instruction::IndirectBr,
nullptr, IBI.getNumOperands()) {
allocHungoffUses(IBI.getNumOperands());
Use *OL = getOperandList();
const Use *InOL = IBI.getOperandList();
for (unsigned i = 0, E = IBI.getNumOperands(); i != E; ++i)
OL[i] = InOL[i];
SubclassOptionalData = IBI.SubclassOptionalData;
}
/// addDestination - Add a destination.
///
void IndirectBrInst::addDestination(BasicBlock *DestBB) {
unsigned OpNo = getNumOperands();
if (OpNo+1 > ReservedSpace)
growOperands(); // Get more space!
// Initialize some new operands.
assert(OpNo < ReservedSpace && "Growing didn't work!");
setNumHungOffUseOperands(OpNo+1);
getOperandList()[OpNo] = DestBB;
}
/// removeDestination - This method removes the specified successor from the
/// indirectbr instruction.
void IndirectBrInst::removeDestination(unsigned idx) {
assert(idx < getNumOperands()-1 && "Successor index out of range!");
unsigned NumOps = getNumOperands();
Use *OL = getOperandList();
// Replace this value with the last one.
OL[idx+1] = OL[NumOps-1];
// Nuke the last value.
OL[NumOps-1].set(nullptr);
setNumHungOffUseOperands(NumOps-1);
}
//===----------------------------------------------------------------------===//
// cloneImpl() implementations
//===----------------------------------------------------------------------===//
// Define these methods here so vtables don't get emitted into every translation
// unit that uses these classes.
GetElementPtrInst *GetElementPtrInst::cloneImpl() const {
return new (getNumOperands()) GetElementPtrInst(*this);
}
BinaryOperator *BinaryOperator::cloneImpl() const {
return Create(getOpcode(), Op<0>(), Op<1>());
}
FCmpInst *FCmpInst::cloneImpl() const {
return new FCmpInst(getPredicate(), Op<0>(), Op<1>());
}
ICmpInst *ICmpInst::cloneImpl() const {
return new ICmpInst(getPredicate(), Op<0>(), Op<1>());
}
ExtractValueInst *ExtractValueInst::cloneImpl() const {
return new ExtractValueInst(*this);
}
InsertValueInst *InsertValueInst::cloneImpl() const {
return new InsertValueInst(*this);
}
AllocaInst *AllocaInst::cloneImpl() const {
AllocaInst *Result = new AllocaInst(getAllocatedType(),
getType()->getAddressSpace(),
(Value *)getOperand(0), getAlignment());
Result->setUsedWithInAlloca(isUsedWithInAlloca());
Result->setSwiftError(isSwiftError());
return Result;
}
LoadInst *LoadInst::cloneImpl() const {
return new LoadInst(getOperand(0), Twine(), isVolatile(),
getAlignment(), getOrdering(), getSyncScopeID());
}
StoreInst *StoreInst::cloneImpl() const {
return new StoreInst(getOperand(0), getOperand(1), isVolatile(),
getAlignment(), getOrdering(), getSyncScopeID());
}
AtomicCmpXchgInst *AtomicCmpXchgInst::cloneImpl() const {
AtomicCmpXchgInst *Result =
new AtomicCmpXchgInst(getOperand(0), getOperand(1), getOperand(2),
getSuccessOrdering(), getFailureOrdering(),
getSyncScopeID());
Result->setVolatile(isVolatile());
Result->setWeak(isWeak());
return Result;
}
AtomicRMWInst *AtomicRMWInst::cloneImpl() const {
AtomicRMWInst *Result =
new AtomicRMWInst(getOperation(), getOperand(0), getOperand(1),
getOrdering(), getSyncScopeID());
Result->setVolatile(isVolatile());
return Result;
}
FenceInst *FenceInst::cloneImpl() const {
return new FenceInst(getContext(), getOrdering(), getSyncScopeID());
}
TruncInst *TruncInst::cloneImpl() const {
return new TruncInst(getOperand(0), getType());
}
ZExtInst *ZExtInst::cloneImpl() const {
return new ZExtInst(getOperand(0), getType());
}
SExtInst *SExtInst::cloneImpl() const {
return new SExtInst(getOperand(0), getType());
}
FPTruncInst *FPTruncInst::cloneImpl() const {
return new FPTruncInst(getOperand(0), getType());
}
FPExtInst *FPExtInst::cloneImpl() const {
return new FPExtInst(getOperand(0), getType());
}
UIToFPInst *UIToFPInst::cloneImpl() const {
return new UIToFPInst(getOperand(0), getType());
}
SIToFPInst *SIToFPInst::cloneImpl() const {
return new SIToFPInst(getOperand(0), getType());
}
FPToUIInst *FPToUIInst::cloneImpl() const {
return new FPToUIInst(getOperand(0), getType());
}
FPToSIInst *FPToSIInst::cloneImpl() const {
return new FPToSIInst(getOperand(0), getType());
}
PtrToIntInst *PtrToIntInst::cloneImpl() const {
return new PtrToIntInst(getOperand(0), getType());
}
IntToPtrInst *IntToPtrInst::cloneImpl() const {
return new IntToPtrInst(getOperand(0), getType());
}
BitCastInst *BitCastInst::cloneImpl() const {
return new BitCastInst(getOperand(0), getType());
}
AddrSpaceCastInst *AddrSpaceCastInst::cloneImpl() const {
return new AddrSpaceCastInst(getOperand(0), getType());
}
CallInst *CallInst::cloneImpl() const {
if (hasOperandBundles()) {
unsigned DescriptorBytes = getNumOperandBundles() * sizeof(BundleOpInfo);
return new(getNumOperands(), DescriptorBytes) CallInst(*this);
}
return new(getNumOperands()) CallInst(*this);
}
SelectInst *SelectInst::cloneImpl() const {
return SelectInst::Create(getOperand(0), getOperand(1), getOperand(2));
}
VAArgInst *VAArgInst::cloneImpl() const {
return new VAArgInst(getOperand(0), getType());
}
ExtractElementInst *ExtractElementInst::cloneImpl() const {
return ExtractElementInst::Create(getOperand(0), getOperand(1));
}
InsertElementInst *InsertElementInst::cloneImpl() const {
return InsertElementInst::Create(getOperand(0), getOperand(1), getOperand(2));
}
ShuffleVectorInst *ShuffleVectorInst::cloneImpl() const {
return new ShuffleVectorInst(getOperand(0), getOperand(1), getOperand(2));
}
PHINode *PHINode::cloneImpl() const { return new PHINode(*this); }
LandingPadInst *LandingPadInst::cloneImpl() const {
return new LandingPadInst(*this);
}
ReturnInst *ReturnInst::cloneImpl() const {
return new(getNumOperands()) ReturnInst(*this);
}
BranchInst *BranchInst::cloneImpl() const {
return new(getNumOperands()) BranchInst(*this);
}
SwitchInst *SwitchInst::cloneImpl() const { return new SwitchInst(*this); }
IndirectBrInst *IndirectBrInst::cloneImpl() const {
return new IndirectBrInst(*this);
}
InvokeInst *InvokeInst::cloneImpl() const {
if (hasOperandBundles()) {
unsigned DescriptorBytes = getNumOperandBundles() * sizeof(BundleOpInfo);
return new(getNumOperands(), DescriptorBytes) InvokeInst(*this);
}
return new(getNumOperands()) InvokeInst(*this);
}
ResumeInst *ResumeInst::cloneImpl() const { return new (1) ResumeInst(*this); }
CleanupReturnInst *CleanupReturnInst::cloneImpl() const {
return new (getNumOperands()) CleanupReturnInst(*this);
}
CatchReturnInst *CatchReturnInst::cloneImpl() const {
return new (getNumOperands()) CatchReturnInst(*this);
}
CatchSwitchInst *CatchSwitchInst::cloneImpl() const {
return new CatchSwitchInst(*this);
}
FuncletPadInst *FuncletPadInst::cloneImpl() const {
return new (getNumOperands()) FuncletPadInst(*this);
}
UnreachableInst *UnreachableInst::cloneImpl() const {
LLVMContext &Context = getContext();
return new UnreachableInst(Context);
}