2017-05-16 05:57:41 +08:00
|
|
|
//===- Instructions.cpp - Implement the LLVM instructions -----------------===//
|
2005-04-22 07:48:37 +08:00
|
|
|
//
|
2004-07-29 20:33:25 +08:00
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 04:36:04 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2005-04-22 07:48:37 +08:00
|
|
|
//
|
2004-07-29 20:33:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2005-01-29 08:35:16 +08:00
|
|
|
// This file implements all of the non-inline methods for the LLVM instruction
|
|
|
|
// classes.
|
2004-07-29 20:33:25 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/IR/Instructions.h"
|
2009-09-24 02:32:25 +08:00
|
|
|
#include "LLVMContextImpl.h"
|
2017-05-16 05:57:41 +08:00
|
|
|
#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"
|
2014-03-04 19:01:28 +08:00
|
|
|
#include "llvm/IR/CallSite.h"
|
2017-05-16 05:57:41 +08:00
|
|
|
#include "llvm/IR/Constant.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Constants.h"
|
|
|
|
#include "llvm/IR/DataLayout.h"
|
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
|
|
#include "llvm/IR/Function.h"
|
2017-05-16 05:57:41 +08:00
|
|
|
#include "llvm/IR/InstrTypes.h"
|
|
|
|
#include "llvm/IR/Instruction.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Metadata.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Module.h"
|
|
|
|
#include "llvm/IR/Operator.h"
|
2017-05-16 05:57:41 +08:00
|
|
|
#include "llvm/IR/Type.h"
|
|
|
|
#include "llvm/IR/Value.h"
|
|
|
|
#include "llvm/Support/AtomicOrdering.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2007-04-23 03:24:39 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2017-05-16 05:57:41 +08:00
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <vector>
|
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2008-01-03 07:42:30 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CallSite Class
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-03-24 21:21:49 +08:00
|
|
|
User::op_iterator CallSite::getCallee() const {
|
|
|
|
Instruction *II(getInstruction());
|
|
|
|
return isCall()
|
2010-08-06 05:25:49 +08:00
|
|
|
? cast<CallInst>(II)->op_end() - 1 // Skip Callee
|
2010-07-16 17:38:02 +08:00
|
|
|
: cast<InvokeInst>(II)->op_end() - 3; // Skip BB, BB, Callee
|
2010-03-24 21:21:49 +08:00
|
|
|
}
|
|
|
|
|
2007-12-10 10:14:30 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TerminatorInst Class
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-05-12 05:26:55 +08:00
|
|
|
unsigned TerminatorInst::getNumSuccessors() const {
|
|
|
|
switch (getOpcode()) {
|
|
|
|
#define HANDLE_TERM_INST(N, OPC, CLASS) \
|
|
|
|
case Instruction::OPC: \
|
2017-06-09 07:23:08 +08:00
|
|
|
return static_cast<const CLASS *>(this)->getNumSuccessors();
|
2017-05-12 05:26:55 +08:00
|
|
|
#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: \
|
2017-06-09 07:23:08 +08:00
|
|
|
return static_cast<const CLASS *>(this)->getSuccessor(idx);
|
2017-05-12 05:26:55 +08:00
|
|
|
#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: \
|
2017-06-09 07:23:08 +08:00
|
|
|
return static_cast<CLASS *>(this)->setSuccessor(idx, B);
|
2017-05-12 05:26:55 +08:00
|
|
|
#include "llvm/IR/Instruction.def"
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
llvm_unreachable("not a terminator");
|
|
|
|
}
|
|
|
|
|
2008-12-29 08:12:50 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// 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";
|
2015-08-14 13:09:07 +08:00
|
|
|
|
|
|
|
if (Op1->getType()->isTokenTy())
|
|
|
|
return "select values cannot have token type";
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
if (VectorType *VT = dyn_cast<VectorType>(Op0->getType())) {
|
2008-12-29 08:12:50 +08:00
|
|
|
// Vector select.
|
2009-08-14 05:58:54 +08:00
|
|
|
if (VT->getElementType() != Type::getInt1Ty(Op0->getContext()))
|
2008-12-29 08:12:50 +08:00
|
|
|
return "vector select condition element type must be i1";
|
2011-07-18 12:54:35 +08:00
|
|
|
VectorType *ET = dyn_cast<VectorType>(Op1->getType());
|
2014-04-09 14:08:46 +08:00
|
|
|
if (!ET)
|
2008-12-29 08:12:50 +08:00
|
|
|
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";
|
2009-08-14 05:58:54 +08:00
|
|
|
} else if (Op0->getType() != Type::getInt1Ty(Op0->getContext())) {
|
2008-12-29 08:12:50 +08:00
|
|
|
return "select condition must be i1 or <n x i1>";
|
|
|
|
}
|
2014-04-09 14:08:46 +08:00
|
|
|
return nullptr;
|
2008-12-29 08:12:50 +08:00
|
|
|
}
|
|
|
|
|
2005-01-29 08:35:16 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// PHINode Class
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
PHINode::PHINode(const PHINode &PN)
|
2015-06-11 06:38:46 +08:00
|
|
|
: Instruction(PN.getType(), Instruction::PHI, nullptr, PN.getNumOperands()),
|
|
|
|
ReservedSpace(PN.getNumOperands()) {
|
|
|
|
allocHungoffUses(PN.getNumOperands());
|
2011-06-23 17:09:15 +08:00
|
|
|
std::copy(PN.op_begin(), PN.op_end(), op_begin());
|
|
|
|
std::copy(PN.block_begin(), PN.block_end(), block_begin());
|
2009-08-26 06:11:20 +08:00
|
|
|
SubclassOptionalData = PN.SubclassOptionalData;
|
2005-01-29 08:35:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// removeIncomingValue - Remove an incoming value. This is useful if a
|
|
|
|
// predecessor basic block is deleted.
|
|
|
|
Value *PHINode::removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty) {
|
2011-06-23 17:09:15 +08:00
|
|
|
Value *Removed = getIncomingValue(Idx);
|
2005-01-29 08:35:16 +08:00
|
|
|
|
|
|
|
// Move everything after this operand down.
|
|
|
|
//
|
|
|
|
// FIXME: we could just swap with the end of the list, then erase. However,
|
2011-06-23 17:09:15 +08:00
|
|
|
// clients might not expect this to happen. The code as it is thrashes the
|
2005-01-29 08:35:16 +08:00
|
|
|
// use/def lists, which is kinda lame.
|
2011-06-23 17:09:15 +08:00
|
|
|
std::copy(op_begin() + Idx + 1, op_end(), op_begin() + Idx);
|
|
|
|
std::copy(block_begin() + Idx + 1, block_end(), block_begin() + Idx);
|
2005-01-29 08:35:16 +08:00
|
|
|
|
|
|
|
// Nuke the last value.
|
2014-04-09 14:08:46 +08:00
|
|
|
Op<-1>().set(nullptr);
|
2015-06-13 01:48:10 +08:00
|
|
|
setNumHungOffUseOperands(getNumOperands() - 1);
|
2005-01-29 08:35:16 +08:00
|
|
|
|
|
|
|
// If the PHI node is dead, because it has zero entries, nuke it now.
|
2011-06-23 17:09:15 +08:00
|
|
|
if (getNumOperands() == 0 && DeletePHIIfEmpty) {
|
2005-01-29 08:35:16 +08:00
|
|
|
// If anyone is using this PHI, make them use a dummy value instead...
|
2009-07-31 07:03:37 +08:00
|
|
|
replaceAllUsesWith(UndefValue::get(getType()));
|
2005-01-29 08:35:16 +08:00
|
|
|
eraseFromParent();
|
|
|
|
}
|
|
|
|
return Removed;
|
|
|
|
}
|
|
|
|
|
2011-04-01 16:00:58 +08:00
|
|
|
/// 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.
|
2005-01-29 08:35:16 +08:00
|
|
|
///
|
2011-04-01 16:00:58 +08:00
|
|
|
void PHINode::growOperands() {
|
2008-05-10 16:32:32 +08:00
|
|
|
unsigned e = getNumOperands();
|
2011-06-23 17:09:15 +08:00
|
|
|
unsigned NumOps = e + e / 2;
|
|
|
|
if (NumOps < 2) NumOps = 2; // 2 op PHI nodes are VERY common.
|
|
|
|
|
2005-01-29 08:35:16 +08:00
|
|
|
ReservedSpace = NumOps;
|
2015-06-11 06:38:41 +08:00
|
|
|
growHungoffUses(ReservedSpace, /* IsPhi */ true);
|
2005-01-29 08:35:16 +08:00
|
|
|
}
|
|
|
|
|
2005-08-05 07:24:19 +08:00
|
|
|
/// hasConstantValue - If the specified PHI node always merges together the same
|
|
|
|
/// value, return the value, otherwise return null.
|
2010-11-17 12:30:22 +08:00
|
|
|
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)
|
2012-07-04 01:10:28 +08:00
|
|
|
if (getIncomingValue(i) != ConstantValue && getIncomingValue(i) != this) {
|
|
|
|
if (ConstantValue != this)
|
2014-04-09 14:08:46 +08:00
|
|
|
return nullptr; // Incoming values not all the same.
|
2012-07-04 01:10:28 +08:00
|
|
|
// The case where the first value is this PHI.
|
|
|
|
ConstantValue = getIncomingValue(i);
|
|
|
|
}
|
2012-07-04 05:15:40 +08:00
|
|
|
if (ConstantValue == this)
|
|
|
|
return UndefValue::get(getType());
|
2010-11-17 12:30:22 +08:00
|
|
|
return ConstantValue;
|
2005-08-05 07:24:19 +08:00
|
|
|
}
|
|
|
|
|
2016-04-15 01:42:47 +08:00
|
|
|
/// 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;
|
|
|
|
}
|
|
|
|
|
2011-08-13 04:24:12 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// LandingPadInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-06-18 04:52:32 +08:00
|
|
|
LandingPadInst::LandingPadInst(Type *RetTy, unsigned NumReservedValues,
|
|
|
|
const Twine &NameStr, Instruction *InsertBefore)
|
|
|
|
: Instruction(RetTy, Instruction::LandingPad, nullptr, 0, InsertBefore) {
|
|
|
|
init(NumReservedValues, NameStr);
|
2011-08-13 04:24:12 +08:00
|
|
|
}
|
|
|
|
|
2015-06-18 04:52:32 +08:00
|
|
|
LandingPadInst::LandingPadInst(Type *RetTy, unsigned NumReservedValues,
|
|
|
|
const Twine &NameStr, BasicBlock *InsertAtEnd)
|
|
|
|
: Instruction(RetTy, Instruction::LandingPad, nullptr, 0, InsertAtEnd) {
|
|
|
|
init(NumReservedValues, NameStr);
|
2011-08-13 04:24:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
LandingPadInst::LandingPadInst(const LandingPadInst &LP)
|
2015-06-11 06:38:46 +08:00
|
|
|
: Instruction(LP.getType(), Instruction::LandingPad, nullptr,
|
|
|
|
LP.getNumOperands()),
|
|
|
|
ReservedSpace(LP.getNumOperands()) {
|
|
|
|
allocHungoffUses(LP.getNumOperands());
|
2015-06-13 01:48:05 +08:00
|
|
|
Use *OL = getOperandList();
|
|
|
|
const Use *InOL = LP.getOperandList();
|
2011-08-13 04:24:12 +08:00
|
|
|
for (unsigned I = 0, E = ReservedSpace; I != E; ++I)
|
|
|
|
OL[I] = InOL[I];
|
|
|
|
|
|
|
|
setCleanup(LP.isCleanup());
|
|
|
|
}
|
|
|
|
|
2015-06-18 04:52:32 +08:00
|
|
|
LandingPadInst *LandingPadInst::Create(Type *RetTy, unsigned NumReservedClauses,
|
2011-08-13 04:24:12 +08:00
|
|
|
const Twine &NameStr,
|
|
|
|
Instruction *InsertBefore) {
|
2015-06-18 04:52:32 +08:00
|
|
|
return new LandingPadInst(RetTy, NumReservedClauses, NameStr, InsertBefore);
|
2011-08-13 04:24:12 +08:00
|
|
|
}
|
|
|
|
|
2015-06-18 04:52:32 +08:00
|
|
|
LandingPadInst *LandingPadInst::Create(Type *RetTy, unsigned NumReservedClauses,
|
2011-08-13 04:24:12 +08:00
|
|
|
const Twine &NameStr,
|
|
|
|
BasicBlock *InsertAtEnd) {
|
2015-06-18 04:52:32 +08:00
|
|
|
return new LandingPadInst(RetTy, NumReservedClauses, NameStr, InsertAtEnd);
|
2011-08-13 04:24:12 +08:00
|
|
|
}
|
|
|
|
|
2015-06-18 04:52:32 +08:00
|
|
|
void LandingPadInst::init(unsigned NumReservedValues, const Twine &NameStr) {
|
2011-08-13 04:24:12 +08:00
|
|
|
ReservedSpace = NumReservedValues;
|
2015-06-18 04:52:32 +08:00
|
|
|
setNumHungOffUseOperands(0);
|
2015-06-11 06:38:46 +08:00
|
|
|
allocHungoffUses(ReservedSpace);
|
2011-08-13 04:24:12 +08:00
|
|
|
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;
|
2015-06-18 04:52:32 +08:00
|
|
|
ReservedSpace = (std::max(e, 1U) + Size / 2) * 2;
|
2015-06-11 06:38:41 +08:00
|
|
|
growHungoffUses(ReservedSpace);
|
2011-08-13 04:24:12 +08:00
|
|
|
}
|
|
|
|
|
2014-06-05 02:51:31 +08:00
|
|
|
void LandingPadInst::addClause(Constant *Val) {
|
2011-08-13 04:24:12 +08:00
|
|
|
unsigned OpNo = getNumOperands();
|
|
|
|
growOperands(1);
|
|
|
|
assert(OpNo < ReservedSpace && "Growing didn't work!");
|
2015-06-13 01:48:10 +08:00
|
|
|
setNumHungOffUseOperands(getNumOperands() + 1);
|
2015-06-13 01:48:05 +08:00
|
|
|
getOperandList()[OpNo] = Val;
|
2011-08-13 04:24:12 +08:00
|
|
|
}
|
2005-01-29 08:35:16 +08:00
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CallInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-04-24 05:36:23 +08:00
|
|
|
void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
|
2015-09-25 03:14:18 +08:00
|
|
|
ArrayRef<OperandBundleDef> Bundles, const Twine &NameStr) {
|
2015-04-24 05:36:23 +08:00
|
|
|
this->FTy = FTy;
|
2015-09-25 03:14:18 +08:00
|
|
|
assert(getNumOperands() == Args.size() + CountBundleInputs(Bundles) + 1 &&
|
|
|
|
"NumOperands not set up?");
|
2010-07-16 17:38:02 +08:00
|
|
|
Op<-1>() = Func;
|
2004-07-29 20:33:25 +08:00
|
|
|
|
2011-07-15 16:37:34 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
assert((Args.size() == FTy->getNumParams() ||
|
|
|
|
(FTy->isVarArg() && Args.size() > FTy->getNumParams())) &&
|
2006-05-03 08:48:22 +08:00
|
|
|
"Calling a function with bad signature!");
|
2011-07-15 16:37:34 +08:00
|
|
|
|
|
|
|
for (unsigned i = 0; i != Args.size(); ++i)
|
2006-05-03 08:48:22 +08:00
|
|
|
assert((i >= FTy->getNumParams() ||
|
2011-07-15 16:37:34 +08:00
|
|
|
FTy->getParamType(i) == Args[i]->getType()) &&
|
2006-05-03 08:48:22 +08:00
|
|
|
"Calling a function with a bad signature!");
|
2011-07-15 16:37:34 +08:00
|
|
|
#endif
|
2004-07-29 20:33:25 +08:00
|
|
|
|
2011-07-15 16:37:34 +08:00
|
|
|
std::copy(Args.begin(), Args.end(), op_begin());
|
2015-09-25 03:14:18 +08:00
|
|
|
|
|
|
|
auto It = populateBundleOperandInfos(Bundles, Args.size());
|
|
|
|
(void)It;
|
|
|
|
assert(It + 1 == op_end() && "Should add up!");
|
|
|
|
|
2011-07-15 16:37:34 +08:00
|
|
|
setName(NameStr);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2011-07-15 16:37:34 +08:00
|
|
|
void CallInst::init(Value *Func, const Twine &NameStr) {
|
2015-04-24 05:36:23 +08:00
|
|
|
FTy =
|
|
|
|
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
|
2015-06-13 01:48:10 +08:00
|
|
|
assert(getNumOperands() == 1 && "NumOperands not set up?");
|
2010-07-16 17:38:02 +08:00
|
|
|
Op<-1>() = Func;
|
2005-04-22 07:48:37 +08:00
|
|
|
|
2007-02-01 12:59:37 +08:00
|
|
|
assert(FTy->getNumParams() == 0 && "Calling a function with bad signature");
|
2004-07-29 20:33:25 +08:00
|
|
|
|
2011-07-15 16:37:34 +08:00
|
|
|
setName(NameStr);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 12:41:11 +08:00
|
|
|
CallInst::CallInst(Value *Func, const Twine &Name,
|
2004-07-29 20:33:25 +08:00
|
|
|
Instruction *InsertBefore)
|
|
|
|
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
|
|
|
|
->getElementType())->getReturnType(),
|
2008-05-10 16:32:32 +08:00
|
|
|
Instruction::Call,
|
|
|
|
OperandTraits<CallInst>::op_end(this) - 1,
|
|
|
|
1, InsertBefore) {
|
2011-07-15 16:37:34 +08:00
|
|
|
init(Func, Name);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 12:41:11 +08:00
|
|
|
CallInst::CallInst(Value *Func, const Twine &Name,
|
2004-07-29 20:33:25 +08:00
|
|
|
BasicBlock *InsertAtEnd)
|
|
|
|
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
|
|
|
|
->getElementType())->getReturnType(),
|
2008-05-10 16:32:32 +08:00
|
|
|
Instruction::Call,
|
|
|
|
OperandTraits<CallInst>::op_end(this) - 1,
|
|
|
|
1, InsertAtEnd) {
|
2011-07-15 16:37:34 +08:00
|
|
|
init(Func, Name);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2005-04-22 07:48:37 +08:00
|
|
|
CallInst::CallInst(const CallInst &CI)
|
2015-04-24 05:36:23 +08:00
|
|
|
: Instruction(CI.getType(), Instruction::Call,
|
|
|
|
OperandTraits<CallInst>::op_end(this) - CI.getNumOperands(),
|
|
|
|
CI.getNumOperands()),
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
Attrs(CI.Attrs), FTy(CI.FTy) {
|
2014-05-07 04:08:20 +08:00
|
|
|
setTailCallKind(CI.getTailCallKind());
|
2009-12-29 10:14:09 +08:00
|
|
|
setCallingConv(CI.getCallingConv());
|
2015-09-25 03:14:18 +08:00
|
|
|
|
2011-07-15 16:37:34 +08:00
|
|
|
std::copy(CI.op_begin(), CI.op_end(), op_begin());
|
2015-09-25 03:14:18 +08:00
|
|
|
std::copy(CI.bundle_op_info_begin(), CI.bundle_op_info_end(),
|
|
|
|
bundle_op_info_begin());
|
2009-08-26 06:11:20 +08:00
|
|
|
SubclassOptionalData = CI.SubclassOptionalData;
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2015-11-18 14:23:38 +08:00
|
|
|
CallInst *CallInst::Create(CallInst *CI, ArrayRef<OperandBundleDef> OpB,
|
|
|
|
Instruction *InsertPt) {
|
2015-12-10 14:39:02 +08:00
|
|
|
std::vector<Value *> Args(CI->arg_begin(), CI->arg_end());
|
2015-11-18 14:23:38 +08:00
|
|
|
|
|
|
|
auto *NewCI = CallInst::Create(CI->getCalledValue(), Args, OpB, CI->getName(),
|
|
|
|
InsertPt);
|
|
|
|
NewCI->setTailCallKind(CI->getTailCallKind());
|
|
|
|
NewCI->setCallingConv(CI->getCallingConv());
|
|
|
|
NewCI->SubclassOptionalData = CI->SubclassOptionalData;
|
2015-12-09 09:01:28 +08:00
|
|
|
NewCI->setAttributes(CI->getAttributes());
|
2016-01-14 14:21:42 +08:00
|
|
|
NewCI->setDebugLoc(CI->getDebugLoc());
|
2015-11-18 14:23:38 +08:00
|
|
|
return NewCI;
|
|
|
|
}
|
|
|
|
|
2016-07-11 07:01:32 +08:00
|
|
|
Value *CallInst::getReturnedArgOperand() const {
|
|
|
|
unsigned Index;
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index)
|
2017-05-04 02:17:31 +08:00
|
|
|
return getArgOperand(Index - AttributeList::FirstArgIndex);
|
2016-07-11 07:01:32 +08:00
|
|
|
if (const Function *F = getCalledFunction())
|
|
|
|
if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) &&
|
|
|
|
Index)
|
2017-05-04 02:17:31 +08:00
|
|
|
return getArgOperand(Index - AttributeList::FirstArgIndex);
|
|
|
|
|
2016-07-11 07:01:32 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-06-15 04:27:35 +08:00
|
|
|
void CallInst::addAttribute(unsigned i, Attribute::AttrKind Kind) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2016-06-15 04:27:35 +08:00
|
|
|
PAL = PAL.addAttribute(getContext(), i, Kind);
|
2008-09-26 05:00:45 +08:00
|
|
|
setAttributes(PAL);
|
2008-05-17 04:39:43 +08:00
|
|
|
}
|
|
|
|
|
2016-06-15 13:14:29 +08:00
|
|
|
void CallInst::addAttribute(unsigned i, Attribute Attr) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2016-06-15 13:14:29 +08:00
|
|
|
PAL = PAL.addAttribute(getContext(), i, Attr);
|
|
|
|
setAttributes(PAL);
|
|
|
|
}
|
|
|
|
|
2017-05-04 02:17:31 +08:00
|
|
|
void CallInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
|
2017-06-01 03:23:09 +08:00
|
|
|
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);
|
2017-05-04 02:17:31 +08:00
|
|
|
}
|
|
|
|
|
2016-06-15 04:27:35 +08:00
|
|
|
void CallInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2016-06-15 04:27:35 +08:00
|
|
|
PAL = PAL.removeAttribute(getContext(), i, Kind);
|
2016-04-22 05:29:10 +08:00
|
|
|
setAttributes(PAL);
|
|
|
|
}
|
|
|
|
|
2016-06-16 01:50:39 +08:00
|
|
|
void CallInst::removeAttribute(unsigned i, StringRef Kind) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2016-06-16 01:50:39 +08:00
|
|
|
PAL = PAL.removeAttribute(getContext(), i, Kind);
|
|
|
|
setAttributes(PAL);
|
|
|
|
}
|
|
|
|
|
2017-05-04 02:17:31 +08:00
|
|
|
void CallInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
|
2017-06-01 03:23:09 +08:00
|
|
|
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);
|
2017-05-04 02:17:31 +08:00
|
|
|
}
|
|
|
|
|
2015-02-15 03:37:54 +08:00
|
|
|
void CallInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2015-02-15 03:37:54 +08:00
|
|
|
PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes);
|
|
|
|
setAttributes(PAL);
|
|
|
|
}
|
|
|
|
|
2015-04-17 04:29:50 +08:00
|
|
|
void CallInst::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2015-04-17 04:29:50 +08:00
|
|
|
PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes);
|
|
|
|
setAttributes(PAL);
|
|
|
|
}
|
|
|
|
|
2017-04-15 04:19:02 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-06-15 04:27:35 +08:00
|
|
|
bool CallInst::paramHasAttr(unsigned i, Attribute::AttrKind Kind) const {
|
2017-04-15 04:19:02 +08:00
|
|
|
assert(i < getNumArgOperands() && "Param index out of bounds!");
|
2015-11-05 04:33:45 +08:00
|
|
|
|
2017-04-15 04:19:02 +08:00
|
|
|
if (Attrs.hasParamAttribute(i, Kind))
|
2012-10-04 01:54:26 +08:00
|
|
|
return true;
|
|
|
|
if (const Function *F = getCalledFunction())
|
2017-04-15 04:19:02 +08:00
|
|
|
return F->getAttributes().hasParamAttribute(i, Kind);
|
2012-10-04 15:18:12 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-11-05 05:05:24 +08:00
|
|
|
bool CallInst::dataOperandHasImpliedAttr(unsigned i,
|
2016-06-15 04:27:35 +08:00
|
|
|
Attribute::AttrKind Kind) const {
|
2015-11-05 09:53:26 +08:00
|
|
|
// There are getNumOperands() - 1 data operands. The last operand is the
|
|
|
|
// callee.
|
|
|
|
assert(i < getNumOperands() && "Data operand index out of bounds!");
|
|
|
|
|
2015-11-05 05:05:24 +08:00
|
|
|
// 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.
|
|
|
|
|
2017-05-24 01:03:28 +08:00
|
|
|
if (i == AttributeList::ReturnIndex)
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-24 01:01:48 +08:00
|
|
|
return hasRetAttr(Kind);
|
|
|
|
|
2017-04-15 04:19:02 +08:00
|
|
|
// FIXME: Avoid these i - 1 calculations and update the API to use zero-based
|
|
|
|
// indices.
|
2015-11-05 05:05:24 +08:00
|
|
|
if (i < (getNumArgOperands() + 1))
|
2017-04-15 04:19:02 +08:00
|
|
|
return paramHasAttr(i - 1, Kind);
|
2015-11-05 05:05:24 +08:00
|
|
|
|
|
|
|
assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) &&
|
|
|
|
"Must be either a call argument or an operand bundle!");
|
2016-06-15 04:27:35 +08:00
|
|
|
return bundleOperandHasAttr(i - 1, Kind);
|
2015-11-05 05:05:24 +08:00
|
|
|
}
|
|
|
|
|
2009-09-10 12:36:43 +08:00
|
|
|
/// IsConstantOne - Return true only if val is constant int 1
|
|
|
|
static bool IsConstantOne(Value *val) {
|
2014-11-14 06:55:19 +08:00
|
|
|
assert(val && "IsConstantOne does not work with nullptr val");
|
2014-09-16 01:56:51 +08:00
|
|
|
const ConstantInt *CVal = dyn_cast<ConstantInt>(val);
|
|
|
|
return CVal && CVal->isOne();
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
2009-10-18 07:52:26 +08:00
|
|
|
static Instruction *createMalloc(Instruction *InsertBefore,
|
2011-07-18 12:54:35 +08:00
|
|
|
BasicBlock *InsertAtEnd, Type *IntPtrTy,
|
2016-04-29 16:07:22 +08:00
|
|
|
Type *AllocTy, Value *AllocSize,
|
|
|
|
Value *ArraySize,
|
|
|
|
ArrayRef<OperandBundleDef> OpB,
|
|
|
|
Function *MallocF, const Twine &Name) {
|
2009-09-10 19:31:39 +08:00
|
|
|
assert(((!InsertBefore && InsertAtEnd) || (InsertBefore && !InsertAtEnd)) &&
|
2009-09-19 03:20:02 +08:00
|
|
|
"createMalloc needs either InsertBefore or InsertAtEnd");
|
|
|
|
|
|
|
|
// malloc(type) becomes:
|
|
|
|
// bitcast (i8* malloc(typeSize)) to type*
|
|
|
|
// malloc(type, arraySize) becomes:
|
2016-02-04 05:34:39 +08:00
|
|
|
// bitcast (i8* malloc(typeSize*arraySize)) to type*
|
2009-11-07 08:16:28 +08:00
|
|
|
if (!ArraySize)
|
|
|
|
ArraySize = ConstantInt::get(IntPtrTy, 1);
|
|
|
|
else if (ArraySize->getType() != IntPtrTy) {
|
|
|
|
if (InsertBefore)
|
2009-11-07 08:36:50 +08:00
|
|
|
ArraySize = CastInst::CreateIntegerCast(ArraySize, IntPtrTy, false,
|
|
|
|
"", InsertBefore);
|
2009-11-07 08:16:28 +08:00
|
|
|
else
|
2009-11-07 08:36:50 +08:00
|
|
|
ArraySize = CastInst::CreateIntegerCast(ArraySize, IntPtrTy, false,
|
|
|
|
"", InsertAtEnd);
|
2009-11-07 08:16:28 +08:00
|
|
|
}
|
2009-09-10 12:36:43 +08:00
|
|
|
|
2009-09-10 19:31:39 +08:00
|
|
|
if (!IsConstantOne(ArraySize)) {
|
2009-09-10 12:36:43 +08:00
|
|
|
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)
|
2009-09-19 03:20:02 +08:00
|
|
|
AllocSize = BinaryOperator::CreateMul(ArraySize, AllocSize,
|
|
|
|
"mallocsize", InsertBefore);
|
2009-09-10 12:36:43 +08:00
|
|
|
else
|
2009-09-19 03:20:02 +08:00
|
|
|
AllocSize = BinaryOperator::CreateMul(ArraySize, AllocSize,
|
|
|
|
"mallocsize", InsertAtEnd);
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
2009-09-10 19:31:39 +08:00
|
|
|
}
|
2009-09-10 12:36:43 +08:00
|
|
|
|
2009-09-19 03:20:02 +08:00
|
|
|
assert(AllocSize->getType() == IntPtrTy && "malloc arg is wrong size");
|
2009-09-10 12:36:43 +08:00
|
|
|
// Create the call to Malloc.
|
2016-02-04 05:34:39 +08:00
|
|
|
BasicBlock *BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
|
|
|
|
Module *M = BB->getParent()->getParent();
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
Type *BPTy = Type::getInt8PtrTy(BB->getContext());
|
2009-11-11 03:53:28 +08:00
|
|
|
Value *MallocFunc = MallocF;
|
|
|
|
if (!MallocFunc)
|
2009-10-17 08:00:19 +08:00
|
|
|
// prototype malloc as "void *malloc(size_t)"
|
2017-04-11 23:01:18 +08:00
|
|
|
MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy);
|
2011-07-18 12:54:35 +08:00
|
|
|
PointerType *AllocPtrType = PointerType::getUnqual(AllocTy);
|
2014-04-09 14:08:46 +08:00
|
|
|
CallInst *MCall = nullptr;
|
|
|
|
Instruction *Result = nullptr;
|
2009-09-19 03:20:02 +08:00
|
|
|
if (InsertBefore) {
|
2016-04-29 16:07:22 +08:00
|
|
|
MCall = CallInst::Create(MallocFunc, AllocSize, OpB, "malloccall",
|
|
|
|
InsertBefore);
|
2009-10-17 08:00:19 +08:00
|
|
|
Result = MCall;
|
|
|
|
if (Result->getType() != AllocPtrType)
|
|
|
|
// Create a cast instruction to convert to the right type...
|
2009-11-07 08:16:28 +08:00
|
|
|
Result = new BitCastInst(MCall, AllocPtrType, Name, InsertBefore);
|
2009-09-19 03:20:02 +08:00
|
|
|
} else {
|
2016-04-29 16:07:22 +08:00
|
|
|
MCall = CallInst::Create(MallocFunc, AllocSize, OpB, "malloccall");
|
2009-10-17 08:00:19 +08:00
|
|
|
Result = MCall;
|
|
|
|
if (Result->getType() != AllocPtrType) {
|
|
|
|
InsertAtEnd->getInstList().push_back(MCall);
|
|
|
|
// Create a cast instruction to convert to the right type...
|
2009-11-07 08:16:28 +08:00
|
|
|
Result = new BitCastInst(MCall, AllocPtrType, Name);
|
2009-10-17 08:00:19 +08:00
|
|
|
}
|
2009-09-19 03:20:02 +08:00
|
|
|
}
|
2009-09-10 12:36:43 +08:00
|
|
|
MCall->setTailCall();
|
2009-11-11 03:53:28 +08:00
|
|
|
if (Function *F = dyn_cast<Function>(MallocFunc)) {
|
|
|
|
MCall->setCallingConv(F->getCallingConv());
|
2017-05-04 02:17:31 +08:00
|
|
|
if (!F->returnDoesNotAlias())
|
|
|
|
F->setReturnDoesNotAlias();
|
2009-11-11 03:53:28 +08:00
|
|
|
}
|
2010-01-05 21:12:22 +08:00
|
|
|
assert(!MCall->getType()->isVoidTy() && "Malloc has void return type");
|
2009-09-19 03:20:02 +08:00
|
|
|
|
2009-10-17 08:00:19 +08:00
|
|
|
return Result;
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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.
|
2009-10-18 07:52:26 +08:00
|
|
|
Instruction *CallInst::CreateMalloc(Instruction *InsertBefore,
|
2011-07-18 12:54:35 +08:00
|
|
|
Type *IntPtrTy, Type *AllocTy,
|
2009-11-07 08:16:28 +08:00
|
|
|
Value *AllocSize, Value *ArraySize,
|
2016-02-04 05:34:39 +08:00
|
|
|
Function *MallocF,
|
2009-11-07 08:16:28 +08:00
|
|
|
const Twine &Name) {
|
2014-04-09 14:08:46 +08:00
|
|
|
return createMalloc(InsertBefore, nullptr, IntPtrTy, AllocTy, AllocSize,
|
2016-04-29 16:07:22 +08:00
|
|
|
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);
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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.
|
2009-10-18 07:52:26 +08:00
|
|
|
Instruction *CallInst::CreateMalloc(BasicBlock *InsertAtEnd,
|
2011-07-18 12:54:35 +08:00
|
|
|
Type *IntPtrTy, Type *AllocTy,
|
2009-11-07 08:16:28 +08:00
|
|
|
Value *AllocSize, Value *ArraySize,
|
|
|
|
Function *MallocF, const Twine &Name) {
|
2014-04-09 14:08:46 +08:00
|
|
|
return createMalloc(nullptr, InsertAtEnd, IntPtrTy, AllocTy, AllocSize,
|
2016-04-29 16:07:22 +08:00
|
|
|
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);
|
2009-09-10 12:36:43 +08:00
|
|
|
}
|
2007-11-29 01:07:01 +08:00
|
|
|
|
2016-04-29 16:07:22 +08:00
|
|
|
static Instruction *createFree(Value *Source,
|
|
|
|
ArrayRef<OperandBundleDef> Bundles,
|
|
|
|
Instruction *InsertBefore,
|
2009-10-24 12:23:03 +08:00
|
|
|
BasicBlock *InsertAtEnd) {
|
|
|
|
assert(((!InsertBefore && InsertAtEnd) || (InsertBefore && !InsertAtEnd)) &&
|
|
|
|
"createFree needs either InsertBefore or InsertAtEnd");
|
2010-02-16 19:11:14 +08:00
|
|
|
assert(Source->getType()->isPointerTy() &&
|
2009-10-24 12:23:03 +08:00
|
|
|
"Can not free something of nonpointer type!");
|
|
|
|
|
2016-02-04 05:34:39 +08:00
|
|
|
BasicBlock *BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd;
|
|
|
|
Module *M = BB->getParent()->getParent();
|
2009-10-24 12:23:03 +08:00
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
Type *VoidTy = Type::getVoidTy(M->getContext());
|
|
|
|
Type *IntPtrTy = Type::getInt8PtrTy(M->getContext());
|
2009-10-24 12:23:03 +08:00
|
|
|
// prototype free as "void free(void*)"
|
2017-04-11 23:01:18 +08:00
|
|
|
Value *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy);
|
2016-02-04 05:34:39 +08:00
|
|
|
CallInst *Result = nullptr;
|
2009-10-24 12:23:03 +08:00
|
|
|
Value *PtrCast = Source;
|
|
|
|
if (InsertBefore) {
|
|
|
|
if (Source->getType() != IntPtrTy)
|
|
|
|
PtrCast = new BitCastInst(Source, IntPtrTy, "", InsertBefore);
|
2016-04-29 16:07:22 +08:00
|
|
|
Result = CallInst::Create(FreeFunc, PtrCast, Bundles, "", InsertBefore);
|
2009-10-24 12:23:03 +08:00
|
|
|
} else {
|
|
|
|
if (Source->getType() != IntPtrTy)
|
|
|
|
PtrCast = new BitCastInst(Source, IntPtrTy, "", InsertAtEnd);
|
2016-04-29 16:07:22 +08:00
|
|
|
Result = CallInst::Create(FreeFunc, PtrCast, Bundles, "");
|
2009-10-24 12:23:03 +08:00
|
|
|
}
|
|
|
|
Result->setTailCall();
|
2009-11-09 15:12:01 +08:00
|
|
|
if (Function *F = dyn_cast<Function>(FreeFunc))
|
|
|
|
Result->setCallingConv(F->getCallingConv());
|
2009-10-24 12:23:03 +08:00
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// CreateFree - Generate the IR for a call to the builtin free function.
|
2016-02-04 05:34:39 +08:00
|
|
|
Instruction *CallInst::CreateFree(Value *Source, Instruction *InsertBefore) {
|
2016-04-29 16:07:22 +08:00
|
|
|
return createFree(Source, None, InsertBefore, nullptr);
|
|
|
|
}
|
|
|
|
Instruction *CallInst::CreateFree(Value *Source,
|
|
|
|
ArrayRef<OperandBundleDef> Bundles,
|
|
|
|
Instruction *InsertBefore) {
|
|
|
|
return createFree(Source, Bundles, InsertBefore, nullptr);
|
2009-10-24 12:23:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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.
|
2016-02-04 05:34:39 +08:00
|
|
|
Instruction *CallInst::CreateFree(Value *Source, BasicBlock *InsertAtEnd) {
|
2016-04-29 16:07:22 +08:00
|
|
|
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);
|
2009-10-24 12:23:03 +08:00
|
|
|
assert(FreeCall && "CreateFree did not create a CallInst");
|
|
|
|
return FreeCall;
|
|
|
|
}
|
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// InvokeInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-05-14 02:35:26 +08:00
|
|
|
void InvokeInst::init(FunctionType *FTy, Value *Fn, BasicBlock *IfNormal,
|
|
|
|
BasicBlock *IfException, ArrayRef<Value *> Args,
|
2015-09-25 03:14:18 +08:00
|
|
|
ArrayRef<OperandBundleDef> Bundles,
|
2015-05-14 02:35:26 +08:00
|
|
|
const Twine &NameStr) {
|
|
|
|
this->FTy = FTy;
|
2015-04-24 05:36:23 +08:00
|
|
|
|
2015-09-25 03:14:18 +08:00
|
|
|
assert(getNumOperands() == 3 + Args.size() + CountBundleInputs(Bundles) &&
|
|
|
|
"NumOperands not set up?");
|
2010-03-24 21:21:49 +08:00
|
|
|
Op<-3>() = Fn;
|
|
|
|
Op<-2>() = IfNormal;
|
|
|
|
Op<-1>() = IfException;
|
2011-07-15 16:37:34 +08:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
assert(((Args.size() == FTy->getNumParams()) ||
|
|
|
|
(FTy->isVarArg() && Args.size() > FTy->getNumParams())) &&
|
2010-03-23 21:45:54 +08:00
|
|
|
"Invoking a function with bad signature");
|
2005-04-22 07:48:37 +08:00
|
|
|
|
2011-07-15 16:37:34 +08:00
|
|
|
for (unsigned i = 0, e = Args.size(); i != e; i++)
|
2006-05-03 08:48:22 +08:00
|
|
|
assert((i >= FTy->getNumParams() ||
|
2007-02-13 09:04:01 +08:00
|
|
|
FTy->getParamType(i) == Args[i]->getType()) &&
|
2006-05-03 08:48:22 +08:00
|
|
|
"Invoking a function with a bad signature!");
|
2011-07-15 16:37:34 +08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
std::copy(Args.begin(), Args.end(), op_begin());
|
2015-09-25 03:14:18 +08:00
|
|
|
|
|
|
|
auto It = populateBundleOperandInfos(Bundles, Args.size());
|
|
|
|
(void)It;
|
|
|
|
assert(It + 3 == op_end() && "Should add up!");
|
|
|
|
|
2011-07-15 16:37:34 +08:00
|
|
|
setName(NameStr);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2005-04-22 07:48:37 +08:00
|
|
|
InvokeInst::InvokeInst(const InvokeInst &II)
|
2015-04-24 05:36:23 +08:00
|
|
|
: TerminatorInst(II.getType(), Instruction::Invoke,
|
|
|
|
OperandTraits<InvokeInst>::op_end(this) -
|
|
|
|
II.getNumOperands(),
|
|
|
|
II.getNumOperands()),
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
Attrs(II.Attrs), FTy(II.FTy) {
|
2009-12-29 10:14:09 +08:00
|
|
|
setCallingConv(II.getCallingConv());
|
2011-07-15 16:37:34 +08:00
|
|
|
std::copy(II.op_begin(), II.op_end(), op_begin());
|
2015-09-25 03:14:18 +08:00
|
|
|
std::copy(II.bundle_op_info_begin(), II.bundle_op_info_end(),
|
|
|
|
bundle_op_info_begin());
|
2009-08-26 06:11:20 +08:00
|
|
|
SubclassOptionalData = II.SubclassOptionalData;
|
2005-01-29 08:35:16 +08:00
|
|
|
}
|
|
|
|
|
2015-11-18 14:23:38 +08:00
|
|
|
InvokeInst *InvokeInst::Create(InvokeInst *II, ArrayRef<OperandBundleDef> OpB,
|
|
|
|
Instruction *InsertPt) {
|
2015-12-10 14:39:02 +08:00
|
|
|
std::vector<Value *> Args(II->arg_begin(), II->arg_end());
|
2015-11-18 14:23:38 +08:00
|
|
|
|
|
|
|
auto *NewII = InvokeInst::Create(II->getCalledValue(), II->getNormalDest(),
|
|
|
|
II->getUnwindDest(), Args, OpB,
|
|
|
|
II->getName(), InsertPt);
|
|
|
|
NewII->setCallingConv(II->getCallingConv());
|
|
|
|
NewII->SubclassOptionalData = II->SubclassOptionalData;
|
2015-12-09 09:01:28 +08:00
|
|
|
NewII->setAttributes(II->getAttributes());
|
2016-01-14 14:21:42 +08:00
|
|
|
NewII->setDebugLoc(II->getDebugLoc());
|
2015-11-18 14:23:38 +08:00
|
|
|
return NewII;
|
|
|
|
}
|
|
|
|
|
2016-07-11 07:01:32 +08:00
|
|
|
Value *InvokeInst::getReturnedArgOperand() const {
|
|
|
|
unsigned Index;
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
if (Attrs.hasAttrSomewhere(Attribute::Returned, &Index) && Index)
|
2017-05-04 02:17:31 +08:00
|
|
|
return getArgOperand(Index - AttributeList::FirstArgIndex);
|
2016-07-11 07:01:32 +08:00
|
|
|
if (const Function *F = getCalledFunction())
|
|
|
|
if (F->getAttributes().hasAttrSomewhere(Attribute::Returned, &Index) &&
|
|
|
|
Index)
|
2017-05-04 02:17:31 +08:00
|
|
|
return getArgOperand(Index - AttributeList::FirstArgIndex);
|
|
|
|
|
2016-07-11 07:01:32 +08:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-04-15 04:19:02 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-06-15 04:27:35 +08:00
|
|
|
bool InvokeInst::paramHasAttr(unsigned i, Attribute::AttrKind Kind) const {
|
2017-04-15 04:19:02 +08:00
|
|
|
assert(i < getNumArgOperands() && "Param index out of bounds!");
|
2015-11-05 04:33:45 +08:00
|
|
|
|
2017-04-15 04:19:02 +08:00
|
|
|
if (Attrs.hasParamAttribute(i, Kind))
|
2012-10-04 15:18:12 +08:00
|
|
|
return true;
|
|
|
|
if (const Function *F = getCalledFunction())
|
2017-04-15 04:19:02 +08:00
|
|
|
return F->getAttributes().hasParamAttribute(i, Kind);
|
2012-10-04 15:18:12 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-11-05 05:05:24 +08:00
|
|
|
bool InvokeInst::dataOperandHasImpliedAttr(unsigned i,
|
2016-06-15 04:27:35 +08:00
|
|
|
Attribute::AttrKind Kind) const {
|
2015-11-05 09:53:26 +08:00
|
|
|
// 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!");
|
|
|
|
|
2015-11-05 05:05:24 +08:00
|
|
|
// 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.
|
|
|
|
|
2017-05-24 01:03:28 +08:00
|
|
|
if (i == AttributeList::ReturnIndex)
|
[IR] Switch AttributeList to use an array for O(1) access
Summary:
Before this change, AttributeLists stored a pair of index and
AttributeSet. This is memory efficient if most arguments do not have
attributes. However, it requires doing a search over the pairs to test
an argument or function attribute. Profiling shows that this loop was
0.76% of the time in 'opt -O2' of sqlite3.c, because LLVM constantly
tests values for nullability.
This was worth about 2.5% of mid-level optimization cycles on the
sqlite3 amalgamation. Here are the full perf results:
https://reviews.llvm.org/P7995
Here are just the before and after cycle counts:
```
$ perf stat -r 5 ./opt_before -O2 sqlite3.bc -o /dev/null
13,274,181,184 cycles # 3.047 GHz ( +- 0.28% )
$ perf stat -r 5 ./opt_after -O2 sqlite3.bc -o /dev/null
12,906,927,263 cycles # 3.043 GHz ( +- 0.51% )
```
This patch *does not* change the indices used to query attributes, as
requested by reviewers. Tracking whether an index is usable for array
indexing is a huge pain that affects many of the internal APIs, so it
would be good to come back later and do a cleanup to remove this
internal adjustment.
Reviewers: pete, chandlerc
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D32819
llvm-svn: 303654
2017-05-24 01:01:48 +08:00
|
|
|
return hasRetAttr(Kind);
|
|
|
|
|
2017-04-15 04:19:02 +08:00
|
|
|
// FIXME: Avoid these i - 1 calculations and update the API to use zero-based
|
|
|
|
// indices.
|
2015-11-05 05:05:24 +08:00
|
|
|
if (i < (getNumArgOperands() + 1))
|
2017-04-15 04:19:02 +08:00
|
|
|
return paramHasAttr(i - 1, Kind);
|
2015-11-05 05:05:24 +08:00
|
|
|
|
|
|
|
assert(hasOperandBundles() && i >= (getBundleOperandsStartIndex() + 1) &&
|
|
|
|
"Must be either an invoke argument or an operand bundle!");
|
2016-06-15 04:27:35 +08:00
|
|
|
return bundleOperandHasAttr(i - 1, Kind);
|
2015-11-05 05:05:24 +08:00
|
|
|
}
|
|
|
|
|
2016-06-15 04:27:35 +08:00
|
|
|
void InvokeInst::addAttribute(unsigned i, Attribute::AttrKind Kind) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2016-06-15 04:27:35 +08:00
|
|
|
PAL = PAL.addAttribute(getContext(), i, Kind);
|
2008-09-26 05:00:45 +08:00
|
|
|
setAttributes(PAL);
|
2008-05-17 04:39:43 +08:00
|
|
|
}
|
|
|
|
|
2016-06-15 13:14:29 +08:00
|
|
|
void InvokeInst::addAttribute(unsigned i, Attribute Attr) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2016-06-15 13:14:29 +08:00
|
|
|
PAL = PAL.addAttribute(getContext(), i, Attr);
|
|
|
|
setAttributes(PAL);
|
|
|
|
}
|
|
|
|
|
2017-05-04 02:17:31 +08:00
|
|
|
void InvokeInst::addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
|
2017-06-01 03:23:09 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
|
|
|
PAL = PAL.addParamAttribute(getContext(), ArgNo, Kind);
|
|
|
|
setAttributes(PAL);
|
2017-05-04 02:17:31 +08:00
|
|
|
}
|
|
|
|
|
2016-06-15 04:27:35 +08:00
|
|
|
void InvokeInst::removeAttribute(unsigned i, Attribute::AttrKind Kind) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2016-06-15 04:27:35 +08:00
|
|
|
PAL = PAL.removeAttribute(getContext(), i, Kind);
|
2016-04-22 05:29:10 +08:00
|
|
|
setAttributes(PAL);
|
|
|
|
}
|
|
|
|
|
2016-06-16 01:50:39 +08:00
|
|
|
void InvokeInst::removeAttribute(unsigned i, StringRef Kind) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2016-06-16 01:50:39 +08:00
|
|
|
PAL = PAL.removeAttribute(getContext(), i, Kind);
|
|
|
|
setAttributes(PAL);
|
|
|
|
}
|
|
|
|
|
2017-05-04 02:17:31 +08:00
|
|
|
void InvokeInst::removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind) {
|
2017-06-01 03:23:09 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
|
|
|
PAL = PAL.removeParamAttribute(getContext(), ArgNo, Kind);
|
|
|
|
setAttributes(PAL);
|
2017-05-04 02:17:31 +08:00
|
|
|
}
|
|
|
|
|
2015-02-15 03:37:54 +08:00
|
|
|
void InvokeInst::addDereferenceableAttr(unsigned i, uint64_t Bytes) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2015-02-15 03:37:54 +08:00
|
|
|
PAL = PAL.addDereferenceableAttr(getContext(), i, Bytes);
|
|
|
|
setAttributes(PAL);
|
|
|
|
}
|
|
|
|
|
2015-04-17 04:29:50 +08:00
|
|
|
void InvokeInst::addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes) {
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList PAL = getAttributes();
|
2015-04-17 04:29:50 +08:00
|
|
|
PAL = PAL.addDereferenceableOrNullAttr(getContext(), i, Bytes);
|
|
|
|
setAttributes(PAL);
|
|
|
|
}
|
|
|
|
|
2011-08-13 04:24:12 +08:00
|
|
|
LandingPadInst *InvokeInst::getLandingPadInst() const {
|
|
|
|
return cast<LandingPadInst>(getUnwindDest()->getFirstNonPHI());
|
|
|
|
}
|
2007-11-29 01:07:01 +08:00
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ReturnInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-02-24 08:55:48 +08:00
|
|
|
ReturnInst::ReturnInst(const ReturnInst &RI)
|
2009-08-14 05:58:54 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(RI.getContext()), Instruction::Ret,
|
2008-07-23 08:34:11 +08:00
|
|
|
OperandTraits<ReturnInst>::op_end(this) -
|
|
|
|
RI.getNumOperands(),
|
2008-05-10 16:32:32 +08:00
|
|
|
RI.getNumOperands()) {
|
2008-07-23 08:34:11 +08:00
|
|
|
if (RI.getNumOperands())
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = RI.Op<0>();
|
2009-08-26 06:11:20 +08:00
|
|
|
SubclassOptionalData = RI.SubclassOptionalData;
|
2007-02-24 08:55:48 +08:00
|
|
|
}
|
|
|
|
|
2009-08-14 05:58:54 +08:00
|
|
|
ReturnInst::ReturnInst(LLVMContext &C, Value *retVal, Instruction *InsertBefore)
|
|
|
|
: TerminatorInst(Type::getVoidTy(C), Instruction::Ret,
|
2008-07-23 08:34:11 +08:00
|
|
|
OperandTraits<ReturnInst>::op_end(this) - !!retVal, !!retVal,
|
|
|
|
InsertBefore) {
|
2008-02-27 02:49:29 +08:00
|
|
|
if (retVal)
|
2008-07-23 08:34:11 +08:00
|
|
|
Op<0>() = retVal;
|
2007-02-24 08:55:48 +08:00
|
|
|
}
|
2017-05-16 05:57:41 +08:00
|
|
|
|
2009-08-14 05:58:54 +08:00
|
|
|
ReturnInst::ReturnInst(LLVMContext &C, Value *retVal, BasicBlock *InsertAtEnd)
|
|
|
|
: TerminatorInst(Type::getVoidTy(C), Instruction::Ret,
|
2008-07-23 08:34:11 +08:00
|
|
|
OperandTraits<ReturnInst>::op_end(this) - !!retVal, !!retVal,
|
|
|
|
InsertAtEnd) {
|
2008-02-27 02:49:29 +08:00
|
|
|
if (retVal)
|
2008-07-23 08:34:11 +08:00
|
|
|
Op<0>() = retVal;
|
2007-02-24 08:55:48 +08:00
|
|
|
}
|
2017-05-16 05:57:41 +08:00
|
|
|
|
2009-08-14 05:58:54 +08:00
|
|
|
ReturnInst::ReturnInst(LLVMContext &Context, BasicBlock *InsertAtEnd)
|
|
|
|
: TerminatorInst(Type::getVoidTy(Context), Instruction::Ret,
|
2008-07-23 08:34:11 +08:00
|
|
|
OperandTraits<ReturnInst>::op_end(this), 0, InsertAtEnd) {
|
2004-11-18 05:02:25 +08:00
|
|
|
}
|
|
|
|
|
2011-07-31 14:30:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2015-08-01 01:58:14 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CleanupReturnInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
CleanupReturnInst::CleanupReturnInst(const CleanupReturnInst &CRI)
|
|
|
|
: TerminatorInst(CRI.getType(), Instruction::CleanupRet,
|
|
|
|
OperandTraits<CleanupReturnInst>::op_end(this) -
|
|
|
|
CRI.getNumOperands(),
|
|
|
|
CRI.getNumOperands()) {
|
2015-08-04 16:21:40 +08:00
|
|
|
setInstructionSubclassData(CRI.getSubclassDataFromInstruction());
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
Op<0>() = CRI.Op<0>();
|
2015-08-23 08:26:33 +08:00
|
|
|
if (CRI.hasUnwindDest())
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
Op<1>() = CRI.Op<1>();
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
void CleanupReturnInst::init(Value *CleanupPad, BasicBlock *UnwindBB) {
|
2015-08-01 01:58:14 +08:00
|
|
|
if (UnwindBB)
|
|
|
|
setInstructionSubclassData(getSubclassDataFromInstruction() | 1);
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
Op<0>() = CleanupPad;
|
2015-08-01 01:58:14 +08:00
|
|
|
if (UnwindBB)
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
Op<1>() = UnwindBB;
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
CleanupReturnInst::CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB,
|
|
|
|
unsigned Values, Instruction *InsertBefore)
|
2015-08-23 08:26:33 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(CleanupPad->getContext()),
|
|
|
|
Instruction::CleanupRet,
|
2015-08-01 01:58:14 +08:00
|
|
|
OperandTraits<CleanupReturnInst>::op_end(this) - Values,
|
|
|
|
Values, InsertBefore) {
|
2015-08-23 08:26:33 +08:00
|
|
|
init(CleanupPad, UnwindBB);
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
CleanupReturnInst::CleanupReturnInst(Value *CleanupPad, BasicBlock *UnwindBB,
|
|
|
|
unsigned Values, BasicBlock *InsertAtEnd)
|
2015-08-23 08:26:33 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(CleanupPad->getContext()),
|
|
|
|
Instruction::CleanupRet,
|
2015-08-01 01:58:14 +08:00
|
|
|
OperandTraits<CleanupReturnInst>::op_end(this) - Values,
|
|
|
|
Values, InsertAtEnd) {
|
2015-08-23 08:26:33 +08:00
|
|
|
init(CleanupPad, UnwindBB);
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CatchReturnInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
void CatchReturnInst::init(Value *CatchPad, BasicBlock *BB) {
|
2015-08-23 08:26:33 +08:00
|
|
|
Op<0>() = CatchPad;
|
|
|
|
Op<1>() = BB;
|
2015-08-15 10:46:08 +08:00
|
|
|
}
|
2015-08-01 01:58:14 +08:00
|
|
|
|
|
|
|
CatchReturnInst::CatchReturnInst(const CatchReturnInst &CRI)
|
|
|
|
: TerminatorInst(Type::getVoidTy(CRI.getContext()), Instruction::CatchRet,
|
2015-08-23 08:26:33 +08:00
|
|
|
OperandTraits<CatchReturnInst>::op_begin(this), 2) {
|
|
|
|
Op<0>() = CRI.Op<0>();
|
|
|
|
Op<1>() = CRI.Op<1>();
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
CatchReturnInst::CatchReturnInst(Value *CatchPad, BasicBlock *BB,
|
2015-08-15 10:46:08 +08:00
|
|
|
Instruction *InsertBefore)
|
2015-08-01 01:58:14 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
|
2015-08-23 08:26:33 +08:00
|
|
|
OperandTraits<CatchReturnInst>::op_begin(this), 2,
|
|
|
|
InsertBefore) {
|
|
|
|
init(CatchPad, BB);
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
CatchReturnInst::CatchReturnInst(Value *CatchPad, BasicBlock *BB,
|
2015-08-15 10:46:08 +08:00
|
|
|
BasicBlock *InsertAtEnd)
|
2015-08-01 01:58:14 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(BB->getContext()), Instruction::CatchRet,
|
2015-08-23 08:26:33 +08:00
|
|
|
OperandTraits<CatchReturnInst>::op_begin(this), 2,
|
|
|
|
InsertAtEnd) {
|
|
|
|
init(CatchPad, BB);
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
// CatchSwitchInst Implementation
|
2015-08-01 01:58:14 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
|
|
|
|
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);
|
2015-08-01 01:58:14 +08:00
|
|
|
setName(NameStr);
|
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
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);
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
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];
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
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);
|
|
|
|
}
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
/// 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;
|
|
|
|
}
|
|
|
|
|
2016-01-05 10:37:41 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// 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);
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
2004-10-17 02:08:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// UnreachableInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-08-14 05:58:54 +08:00
|
|
|
UnreachableInst::UnreachableInst(LLVMContext &Context,
|
|
|
|
Instruction *InsertBefore)
|
|
|
|
: TerminatorInst(Type::getVoidTy(Context), Instruction::Unreachable,
|
2014-04-09 14:08:46 +08:00
|
|
|
nullptr, 0, InsertBefore) {
|
2007-02-24 08:55:48 +08:00
|
|
|
}
|
2009-08-14 05:58:54 +08:00
|
|
|
UnreachableInst::UnreachableInst(LLVMContext &Context, BasicBlock *InsertAtEnd)
|
|
|
|
: TerminatorInst(Type::getVoidTy(Context), Instruction::Unreachable,
|
2014-04-09 14:08:46 +08:00
|
|
|
nullptr, 0, InsertAtEnd) {
|
2007-02-24 08:55:48 +08:00
|
|
|
}
|
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// BranchInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2005-01-29 08:35:16 +08:00
|
|
|
void BranchInst::AssertOK() {
|
|
|
|
if (isConditional())
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(getCondition()->getType()->isIntegerTy(1) &&
|
2005-01-29 08:35:16 +08:00
|
|
|
"May only branch on boolean predicates!");
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2007-02-24 08:55:48 +08:00
|
|
|
BranchInst::BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore)
|
2009-08-14 05:58:54 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(IfTrue->getContext()), Instruction::Br,
|
2008-05-10 16:32:32 +08:00
|
|
|
OperandTraits<BranchInst>::op_end(this) - 1,
|
|
|
|
1, InsertBefore) {
|
2014-04-15 14:32:26 +08:00
|
|
|
assert(IfTrue && "Branch destination may not be null!");
|
2009-03-13 02:34:49 +08:00
|
|
|
Op<-1>() = IfTrue;
|
2007-02-24 08:55:48 +08:00
|
|
|
}
|
2017-05-16 05:57:41 +08:00
|
|
|
|
2007-02-24 08:55:48 +08:00
|
|
|
BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond,
|
|
|
|
Instruction *InsertBefore)
|
2009-08-14 05:58:54 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(IfTrue->getContext()), Instruction::Br,
|
2008-05-10 16:32:32 +08:00
|
|
|
OperandTraits<BranchInst>::op_end(this) - 3,
|
|
|
|
3, InsertBefore) {
|
2009-03-13 02:34:49 +08:00
|
|
|
Op<-1>() = IfTrue;
|
|
|
|
Op<-2>() = IfFalse;
|
|
|
|
Op<-3>() = Cond;
|
2007-02-24 08:55:48 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
AssertOK();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd)
|
2009-08-14 05:58:54 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(IfTrue->getContext()), Instruction::Br,
|
2008-05-10 16:32:32 +08:00
|
|
|
OperandTraits<BranchInst>::op_end(this) - 1,
|
|
|
|
1, InsertAtEnd) {
|
2014-04-15 14:32:26 +08:00
|
|
|
assert(IfTrue && "Branch destination may not be null!");
|
2009-03-13 02:34:49 +08:00
|
|
|
Op<-1>() = IfTrue;
|
2007-02-24 08:55:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond,
|
|
|
|
BasicBlock *InsertAtEnd)
|
2009-08-14 05:58:54 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(IfTrue->getContext()), Instruction::Br,
|
2008-05-10 16:32:32 +08:00
|
|
|
OperandTraits<BranchInst>::op_end(this) - 3,
|
|
|
|
3, InsertAtEnd) {
|
2009-03-13 02:34:49 +08:00
|
|
|
Op<-1>() = IfTrue;
|
|
|
|
Op<-2>() = IfFalse;
|
|
|
|
Op<-3>() = Cond;
|
2007-02-24 08:55:48 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
AssertOK();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2005-01-29 08:35:16 +08:00
|
|
|
BranchInst::BranchInst(const BranchInst &BI) :
|
2009-08-14 05:58:54 +08:00
|
|
|
TerminatorInst(Type::getVoidTy(BI.getContext()), Instruction::Br,
|
2008-05-10 16:32:32 +08:00
|
|
|
OperandTraits<BranchInst>::op_end(this) - BI.getNumOperands(),
|
|
|
|
BI.getNumOperands()) {
|
2009-03-13 02:34:49 +08:00
|
|
|
Op<-1>() = BI.Op<-1>();
|
2005-01-29 08:35:16 +08:00
|
|
|
if (BI.getNumOperands() != 1) {
|
|
|
|
assert(BI.getNumOperands() == 3 && "BR can have 1 or 3 operands!");
|
2009-03-13 02:34:49 +08:00
|
|
|
Op<-3>() = BI.Op<-3>();
|
|
|
|
Op<-2>() = BI.Op<-2>();
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
2009-08-26 06:11:20 +08:00
|
|
|
SubclassOptionalData = BI.SubclassOptionalData;
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2011-10-17 09:11:57 +08:00
|
|
|
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.
|
2016-08-23 23:39:03 +08:00
|
|
|
swapProfMetadata();
|
2011-10-17 09:11:57 +08:00
|
|
|
}
|
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2009-10-24 05:09:37 +08:00
|
|
|
// AllocaInst Implementation
|
2004-07-29 20:33:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-07-15 07:09:55 +08:00
|
|
|
static Value *getAISize(LLVMContext &Context, Value *Amt) {
|
2005-01-29 08:35:16 +08:00
|
|
|
if (!Amt)
|
2009-08-14 05:58:54 +08:00
|
|
|
Amt = ConstantInt::get(Type::getInt32Ty(Context), 1);
|
2006-05-10 12:32:43 +08:00
|
|
|
else {
|
|
|
|
assert(!isa<BasicBlock>(Amt) &&
|
2007-10-19 00:10:48 +08:00
|
|
|
"Passed basic block into allocation size parameter! Use other ctor");
|
2010-05-28 09:14:11 +08:00
|
|
|
assert(Amt->getType()->isIntegerTy() &&
|
|
|
|
"Allocation array size is not an integer!");
|
2006-05-10 12:32:43 +08:00
|
|
|
}
|
2005-04-22 07:48:37 +08:00
|
|
|
return Amt;
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2017-04-11 06:27:50 +08:00
|
|
|
AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, const Twine &Name,
|
2009-10-24 05:09:37 +08:00
|
|
|
Instruction *InsertBefore)
|
2017-04-11 06:27:50 +08:00
|
|
|
: AllocaInst(Ty, AddrSpace, /*ArraySize=*/nullptr, Name, InsertBefore) {}
|
2009-10-24 05:09:37 +08:00
|
|
|
|
2017-04-11 06:27:50 +08:00
|
|
|
AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, const Twine &Name,
|
2009-10-24 05:09:37 +08:00
|
|
|
BasicBlock *InsertAtEnd)
|
2017-04-11 06:27:50 +08:00
|
|
|
: AllocaInst(Ty, AddrSpace, /*ArraySize=*/nullptr, Name, InsertAtEnd) {}
|
2009-10-24 05:09:37 +08:00
|
|
|
|
2017-04-11 06:27:50 +08:00
|
|
|
AllocaInst::AllocaInst(Type *Ty, unsigned AddrSpace, Value *ArraySize,
|
2009-10-24 05:09:37 +08:00
|
|
|
const Twine &Name, Instruction *InsertBefore)
|
2017-04-11 06:27:50 +08:00
|
|
|
: 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) {
|
2008-03-25 00:55:58 +08:00
|
|
|
setAlignment(Align);
|
2010-01-05 21:12:22 +08:00
|
|
|
assert(!Ty->isVoidTy() && "Cannot allocate void!");
|
2007-02-13 15:54:42 +08:00
|
|
|
setName(Name);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2017-04-11 06:27:50 +08:00
|
|
|
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),
|
2015-04-30 07:00:35 +08:00
|
|
|
AllocatedType(Ty) {
|
2008-03-25 00:55:58 +08:00
|
|
|
setAlignment(Align);
|
2010-01-05 21:12:22 +08:00
|
|
|
assert(!Ty->isVoidTy() && "Cannot allocate void!");
|
2007-02-13 15:54:42 +08:00
|
|
|
setName(Name);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2009-10-24 05:09:37 +08:00
|
|
|
void AllocaInst::setAlignment(unsigned Align) {
|
2008-03-25 00:55:58 +08:00
|
|
|
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
|
2010-07-29 04:12:04 +08:00
|
|
|
assert(Align <= MaximumAlignment &&
|
|
|
|
"Alignment is greater than MaximumAlignment!");
|
2014-01-18 07:58:17 +08:00
|
|
|
setInstructionSubclassData((getSubclassDataFromInstruction() & ~31) |
|
|
|
|
(Log2_32(Align) + 1));
|
2008-03-25 00:55:58 +08:00
|
|
|
assert(getAlignment() == Align && "Alignment representation error!");
|
|
|
|
}
|
|
|
|
|
2009-10-24 05:09:37 +08:00
|
|
|
bool AllocaInst::isArrayAllocation() const {
|
2007-03-02 04:27:41 +08:00
|
|
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(getOperand(0)))
|
2010-09-27 23:15:44 +08:00
|
|
|
return !CI->isOne();
|
2005-01-29 08:35:16 +08:00
|
|
|
return true;
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2008-11-26 10:54:17 +08:00
|
|
|
/// 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();
|
2014-01-18 07:58:17 +08:00
|
|
|
return Parent == &Parent->getParent()->front() && !isUsedWithInAlloca();
|
2008-11-26 10:54:17 +08:00
|
|
|
}
|
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// LoadInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2005-01-29 08:35:16 +08:00
|
|
|
void LoadInst::AssertOK() {
|
2010-02-16 19:11:14 +08:00
|
|
|
assert(getOperand(0)->getType()->isPointerTy() &&
|
2004-07-29 20:33:25 +08:00
|
|
|
"Ptr must have pointer type.");
|
2011-08-10 07:02:53 +08:00
|
|
|
assert(!(isAtomic() && getAlignment() == 0) &&
|
|
|
|
"Alignment required for atomic load");
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2009-07-25 12:41:11 +08:00
|
|
|
LoadInst::LoadInst(Value *Ptr, const Twine &Name, Instruction *InsertBef)
|
2015-03-06 06:05:26 +08:00
|
|
|
: LoadInst(Ptr, Name, /*isVolatile=*/false, InsertBef) {}
|
2004-07-29 20:33:25 +08:00
|
|
|
|
2009-07-25 12:41:11 +08:00
|
|
|
LoadInst::LoadInst(Value *Ptr, const Twine &Name, BasicBlock *InsertAE)
|
2015-03-06 06:05:26 +08:00
|
|
|
: LoadInst(Ptr, Name, /*isVolatile=*/false, InsertAE) {}
|
2004-07-29 20:33:25 +08:00
|
|
|
|
2015-05-21 05:46:30 +08:00
|
|
|
LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile,
|
2004-07-29 20:33:25 +08:00
|
|
|
Instruction *InsertBef)
|
2015-05-21 05:46:30 +08:00
|
|
|
: LoadInst(Ty, Ptr, Name, isVolatile, /*Align=*/0, InsertBef) {}
|
2011-08-10 07:02:53 +08:00
|
|
|
|
|
|
|
LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
|
|
|
|
BasicBlock *InsertAE)
|
2015-03-06 06:05:26 +08:00
|
|
|
: LoadInst(Ptr, Name, isVolatile, /*Align=*/0, InsertAE) {}
|
2007-04-23 03:24:39 +08:00
|
|
|
|
2015-04-18 03:56:21 +08:00
|
|
|
LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile,
|
2007-04-23 03:24:39 +08:00
|
|
|
unsigned Align, Instruction *InsertBef)
|
2016-04-07 05:19:33 +08:00
|
|
|
: LoadInst(Ty, Ptr, Name, isVolatile, Align, AtomicOrdering::NotAtomic,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::System, InsertBef) {}
|
2004-07-29 20:33:25 +08:00
|
|
|
|
2015-03-06 06:05:26 +08:00
|
|
|
LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
|
2007-07-19 04:51:11 +08:00
|
|
|
unsigned Align, BasicBlock *InsertAE)
|
2016-04-07 05:19:33 +08:00
|
|
|
: LoadInst(Ptr, Name, isVolatile, Align, AtomicOrdering::NotAtomic,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::System, InsertAE) {}
|
2007-07-19 04:51:11 +08:00
|
|
|
|
2015-04-07 04:59:48 +08:00
|
|
|
LoadInst::LoadInst(Type *Ty, Value *Ptr, const Twine &Name, bool isVolatile,
|
2011-08-10 07:02:53 +08:00
|
|
|
unsigned Align, AtomicOrdering Order,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID, Instruction *InsertBef)
|
2015-04-07 04:59:48 +08:00
|
|
|
: UnaryInstruction(Ty, Load, Ptr, InsertBef) {
|
2015-05-21 04:22:31 +08:00
|
|
|
assert(Ty == cast<PointerType>(Ptr->getType())->getElementType());
|
2011-08-10 07:02:53 +08:00
|
|
|
setVolatile(isVolatile);
|
|
|
|
setAlignment(Align);
|
2017-07-12 06:23:00 +08:00
|
|
|
setAtomic(Order, SSID);
|
2011-08-10 07:02:53 +08:00
|
|
|
AssertOK();
|
|
|
|
setName(Name);
|
|
|
|
}
|
|
|
|
|
|
|
|
LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
|
|
|
|
unsigned Align, AtomicOrdering Order,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID,
|
2004-07-29 20:33:25 +08:00
|
|
|
BasicBlock *InsertAE)
|
2005-01-29 08:35:16 +08:00
|
|
|
: UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(),
|
2007-02-24 08:55:48 +08:00
|
|
|
Load, Ptr, InsertAE) {
|
2007-02-13 15:54:42 +08:00
|
|
|
setVolatile(isVolatile);
|
2011-08-10 07:02:53 +08:00
|
|
|
setAlignment(Align);
|
2017-07-12 06:23:00 +08:00
|
|
|
setAtomic(Order, SSID);
|
2007-02-13 15:54:42 +08:00
|
|
|
AssertOK();
|
|
|
|
setName(Name);
|
|
|
|
}
|
|
|
|
|
2009-08-12 02:11:15 +08:00
|
|
|
LoadInst::LoadInst(Value *Ptr, const char *Name, Instruction *InsertBef)
|
|
|
|
: UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(),
|
|
|
|
Load, Ptr, InsertBef) {
|
|
|
|
setVolatile(false);
|
|
|
|
setAlignment(0);
|
2016-04-07 05:19:33 +08:00
|
|
|
setAtomic(AtomicOrdering::NotAtomic);
|
2009-08-12 02:11:15 +08:00
|
|
|
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);
|
2016-04-07 05:19:33 +08:00
|
|
|
setAtomic(AtomicOrdering::NotAtomic);
|
2009-08-12 02:11:15 +08:00
|
|
|
AssertOK();
|
|
|
|
if (Name && Name[0]) setName(Name);
|
|
|
|
}
|
|
|
|
|
2015-05-21 05:46:30 +08:00
|
|
|
LoadInst::LoadInst(Type *Ty, Value *Ptr, const char *Name, bool isVolatile,
|
2009-08-12 02:11:15 +08:00
|
|
|
Instruction *InsertBef)
|
2015-05-21 05:46:30 +08:00
|
|
|
: UnaryInstruction(Ty, Load, Ptr, InsertBef) {
|
|
|
|
assert(Ty == cast<PointerType>(Ptr->getType())->getElementType());
|
2009-08-12 02:11:15 +08:00
|
|
|
setVolatile(isVolatile);
|
|
|
|
setAlignment(0);
|
2016-04-07 05:19:33 +08:00
|
|
|
setAtomic(AtomicOrdering::NotAtomic);
|
2009-08-12 02:11:15 +08:00
|
|
|
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);
|
2016-04-07 05:19:33 +08:00
|
|
|
setAtomic(AtomicOrdering::NotAtomic);
|
2009-08-12 02:11:15 +08:00
|
|
|
AssertOK();
|
|
|
|
if (Name && Name[0]) setName(Name);
|
|
|
|
}
|
|
|
|
|
2007-04-23 03:24:39 +08:00
|
|
|
void LoadInst::setAlignment(unsigned Align) {
|
|
|
|
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
|
2010-07-29 04:12:04 +08:00
|
|
|
assert(Align <= MaximumAlignment &&
|
|
|
|
"Alignment is greater than MaximumAlignment!");
|
2011-08-10 07:02:53 +08:00
|
|
|
setInstructionSubclassData((getSubclassDataFromInstruction() & ~(31 << 1)) |
|
2009-12-29 10:46:09 +08:00
|
|
|
((Log2_32(Align)+1)<<1));
|
2010-07-29 04:12:04 +08:00
|
|
|
assert(getAlignment() == Align && "Alignment representation error!");
|
2007-04-23 03:24:39 +08:00
|
|
|
}
|
2004-07-29 20:33:25 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// StoreInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2005-01-29 08:35:16 +08:00
|
|
|
void StoreInst::AssertOK() {
|
2008-07-29 23:49:41 +08:00
|
|
|
assert(getOperand(0) && getOperand(1) && "Both operands must be non-null!");
|
2010-02-16 19:11:14 +08:00
|
|
|
assert(getOperand(1)->getType()->isPointerTy() &&
|
2005-01-29 08:35:16 +08:00
|
|
|
"Ptr must have pointer type!");
|
|
|
|
assert(getOperand(0)->getType() ==
|
|
|
|
cast<PointerType>(getOperand(1)->getType())->getElementType()
|
|
|
|
&& "Ptr must be a pointer to Val type!");
|
2011-08-10 07:02:53 +08:00
|
|
|
assert(!(isAtomic() && getAlignment() == 0) &&
|
2013-12-21 08:00:49 +08:00
|
|
|
"Alignment required for atomic store");
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2005-01-29 08:35:16 +08:00
|
|
|
StoreInst::StoreInst(Value *val, Value *addr, Instruction *InsertBefore)
|
2015-03-06 06:05:26 +08:00
|
|
|
: StoreInst(val, addr, /*isVolatile=*/false, InsertBefore) {}
|
2004-07-29 20:33:25 +08:00
|
|
|
|
2005-01-29 08:35:16 +08:00
|
|
|
StoreInst::StoreInst(Value *val, Value *addr, BasicBlock *InsertAtEnd)
|
2015-03-06 06:05:26 +08:00
|
|
|
: StoreInst(val, addr, /*isVolatile=*/false, InsertAtEnd) {}
|
2004-07-29 20:33:25 +08:00
|
|
|
|
2005-04-22 07:48:37 +08:00
|
|
|
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
|
2005-01-29 08:35:16 +08:00
|
|
|
Instruction *InsertBefore)
|
2015-03-06 06:05:26 +08:00
|
|
|
: StoreInst(val, addr, isVolatile, /*Align=*/0, InsertBefore) {}
|
2007-04-23 03:24:39 +08:00
|
|
|
|
|
|
|
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
|
2015-03-06 06:05:26 +08:00
|
|
|
BasicBlock *InsertAtEnd)
|
|
|
|
: StoreInst(val, addr, isVolatile, /*Align=*/0, InsertAtEnd) {}
|
|
|
|
|
|
|
|
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, unsigned Align,
|
|
|
|
Instruction *InsertBefore)
|
2016-04-07 05:19:33 +08:00
|
|
|
: StoreInst(val, addr, isVolatile, Align, AtomicOrdering::NotAtomic,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::System, InsertBefore) {}
|
2015-03-06 06:05:26 +08:00
|
|
|
|
|
|
|
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, unsigned Align,
|
|
|
|
BasicBlock *InsertAtEnd)
|
2016-04-07 05:19:33 +08:00
|
|
|
: StoreInst(val, addr, isVolatile, Align, AtomicOrdering::NotAtomic,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::System, InsertAtEnd) {}
|
2011-08-10 07:02:53 +08:00
|
|
|
|
|
|
|
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
|
|
|
|
unsigned Align, AtomicOrdering Order,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID,
|
2011-08-10 07:02:53 +08:00
|
|
|
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);
|
2017-07-12 06:23:00 +08:00
|
|
|
setAtomic(Order, SSID);
|
2011-08-10 07:02:53 +08:00
|
|
|
AssertOK();
|
|
|
|
}
|
|
|
|
|
2005-04-22 07:48:37 +08:00
|
|
|
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
|
2011-08-10 07:02:53 +08:00
|
|
|
unsigned Align, AtomicOrdering Order,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID,
|
2005-01-29 08:35:16 +08:00
|
|
|
BasicBlock *InsertAtEnd)
|
2009-08-14 05:58:54 +08:00
|
|
|
: Instruction(Type::getVoidTy(val->getContext()), Store,
|
2008-05-10 16:32:32 +08:00
|
|
|
OperandTraits<StoreInst>::op_begin(this),
|
|
|
|
OperandTraits<StoreInst>::operands(this),
|
|
|
|
InsertAtEnd) {
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = val;
|
|
|
|
Op<1>() = addr;
|
2005-02-05 09:38:38 +08:00
|
|
|
setVolatile(isVolatile);
|
2011-08-10 07:02:53 +08:00
|
|
|
setAlignment(Align);
|
2017-07-12 06:23:00 +08:00
|
|
|
setAtomic(Order, SSID);
|
2005-01-29 08:35:16 +08:00
|
|
|
AssertOK();
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2007-04-23 03:24:39 +08:00
|
|
|
void StoreInst::setAlignment(unsigned Align) {
|
|
|
|
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
|
2010-07-29 04:12:04 +08:00
|
|
|
assert(Align <= MaximumAlignment &&
|
|
|
|
"Alignment is greater than MaximumAlignment!");
|
2011-08-10 07:02:53 +08:00
|
|
|
setInstructionSubclassData((getSubclassDataFromInstruction() & ~(31 << 1)) |
|
2009-12-29 10:46:09 +08:00
|
|
|
((Log2_32(Align)+1) << 1));
|
2010-07-29 04:12:04 +08:00
|
|
|
assert(getAlignment() == Align && "Alignment representation error!");
|
2007-04-23 03:24:39 +08:00
|
|
|
}
|
|
|
|
|
2011-07-29 05:48:00 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// AtomicCmpXchgInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void AtomicCmpXchgInst::Init(Value *Ptr, Value *Cmp, Value *NewVal,
|
2014-03-11 18:48:52 +08:00
|
|
|
AtomicOrdering SuccessOrdering,
|
|
|
|
AtomicOrdering FailureOrdering,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID) {
|
2011-07-29 05:48:00 +08:00
|
|
|
Op<0>() = Ptr;
|
|
|
|
Op<1>() = Cmp;
|
|
|
|
Op<2>() = NewVal;
|
2014-03-11 18:48:52 +08:00
|
|
|
setSuccessOrdering(SuccessOrdering);
|
|
|
|
setFailureOrdering(FailureOrdering);
|
2017-07-12 06:23:00 +08:00
|
|
|
setSyncScopeID(SSID);
|
2011-07-29 05:48:00 +08:00
|
|
|
|
|
|
|
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!");
|
2016-04-07 05:19:33 +08:00
|
|
|
assert(SuccessOrdering != AtomicOrdering::NotAtomic &&
|
2014-03-11 18:48:52 +08:00
|
|
|
"AtomicCmpXchg instructions must be atomic!");
|
2016-04-07 05:19:33 +08:00
|
|
|
assert(FailureOrdering != AtomicOrdering::NotAtomic &&
|
2011-07-29 05:48:00 +08:00
|
|
|
"AtomicCmpXchg instructions must be atomic!");
|
2016-04-07 05:19:33 +08:00
|
|
|
assert(!isStrongerThan(FailureOrdering, SuccessOrdering) &&
|
|
|
|
"AtomicCmpXchg failure argument shall be no stronger than the success "
|
|
|
|
"argument");
|
|
|
|
assert(FailureOrdering != AtomicOrdering::Release &&
|
|
|
|
FailureOrdering != AtomicOrdering::AcquireRelease &&
|
2014-03-11 18:48:52 +08:00
|
|
|
"AtomicCmpXchg failure ordering cannot include release semantics");
|
2011-07-29 05:48:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
|
2014-03-11 18:48:52 +08:00
|
|
|
AtomicOrdering SuccessOrdering,
|
|
|
|
AtomicOrdering FailureOrdering,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID,
|
2011-07-29 05:48:00 +08:00
|
|
|
Instruction *InsertBefore)
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
: Instruction(
|
2017-05-10 03:31:13 +08:00
|
|
|
StructType::get(Cmp->getType(), Type::getInt1Ty(Cmp->getContext())),
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
AtomicCmpXchg, OperandTraits<AtomicCmpXchgInst>::op_begin(this),
|
|
|
|
OperandTraits<AtomicCmpXchgInst>::operands(this), InsertBefore) {
|
2017-07-12 06:23:00 +08:00
|
|
|
Init(Ptr, Cmp, NewVal, SuccessOrdering, FailureOrdering, SSID);
|
2011-07-29 05:48:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
|
2014-03-11 18:48:52 +08:00
|
|
|
AtomicOrdering SuccessOrdering,
|
|
|
|
AtomicOrdering FailureOrdering,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID,
|
2011-07-29 05:48:00 +08:00
|
|
|
BasicBlock *InsertAtEnd)
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
: Instruction(
|
2017-05-10 03:31:13 +08:00
|
|
|
StructType::get(Cmp->getType(), Type::getInt1Ty(Cmp->getContext())),
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
AtomicCmpXchg, OperandTraits<AtomicCmpXchgInst>::op_begin(this),
|
|
|
|
OperandTraits<AtomicCmpXchgInst>::operands(this), InsertAtEnd) {
|
2017-07-12 06:23:00 +08:00
|
|
|
Init(Ptr, Cmp, NewVal, SuccessOrdering, FailureOrdering, SSID);
|
2011-07-29 05:48:00 +08:00
|
|
|
}
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
|
2011-07-29 05:48:00 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// AtomicRMWInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void AtomicRMWInst::Init(BinOp Operation, Value *Ptr, Value *Val,
|
|
|
|
AtomicOrdering Ordering,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID) {
|
2011-07-29 05:48:00 +08:00
|
|
|
Op<0>() = Ptr;
|
|
|
|
Op<1>() = Val;
|
|
|
|
setOperation(Operation);
|
|
|
|
setOrdering(Ordering);
|
2017-07-12 06:23:00 +08:00
|
|
|
setSyncScopeID(SSID);
|
2011-07-29 05:48:00 +08:00
|
|
|
|
|
|
|
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!");
|
2016-04-07 05:19:33 +08:00
|
|
|
assert(Ordering != AtomicOrdering::NotAtomic &&
|
2011-07-29 05:48:00 +08:00
|
|
|
"AtomicRMW instructions must be atomic!");
|
|
|
|
}
|
|
|
|
|
|
|
|
AtomicRMWInst::AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
|
|
|
|
AtomicOrdering Ordering,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID,
|
2011-07-29 05:48:00 +08:00
|
|
|
Instruction *InsertBefore)
|
|
|
|
: Instruction(Val->getType(), AtomicRMW,
|
|
|
|
OperandTraits<AtomicRMWInst>::op_begin(this),
|
|
|
|
OperandTraits<AtomicRMWInst>::operands(this),
|
|
|
|
InsertBefore) {
|
2017-07-12 06:23:00 +08:00
|
|
|
Init(Operation, Ptr, Val, Ordering, SSID);
|
2011-07-29 05:48:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
AtomicRMWInst::AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
|
|
|
|
AtomicOrdering Ordering,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID,
|
2011-07-29 05:48:00 +08:00
|
|
|
BasicBlock *InsertAtEnd)
|
|
|
|
: Instruction(Val->getType(), AtomicRMW,
|
|
|
|
OperandTraits<AtomicRMWInst>::op_begin(this),
|
|
|
|
OperandTraits<AtomicRMWInst>::operands(this),
|
|
|
|
InsertAtEnd) {
|
2017-07-12 06:23:00 +08:00
|
|
|
Init(Operation, Ptr, Val, Ordering, SSID);
|
2011-07-29 05:48:00 +08:00
|
|
|
}
|
|
|
|
|
2011-07-26 07:16:38 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// FenceInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID,
|
2011-07-26 07:16:38 +08:00
|
|
|
Instruction *InsertBefore)
|
2014-04-09 14:08:46 +08:00
|
|
|
: Instruction(Type::getVoidTy(C), Fence, nullptr, 0, InsertBefore) {
|
2011-07-26 07:16:38 +08:00
|
|
|
setOrdering(Ordering);
|
2017-07-12 06:23:00 +08:00
|
|
|
setSyncScopeID(SSID);
|
2011-07-26 07:16:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FenceInst::FenceInst(LLVMContext &C, AtomicOrdering Ordering,
|
2017-07-12 06:23:00 +08:00
|
|
|
SyncScope::ID SSID,
|
2011-07-26 07:16:38 +08:00
|
|
|
BasicBlock *InsertAtEnd)
|
2014-04-09 14:08:46 +08:00
|
|
|
: Instruction(Type::getVoidTy(C), Fence, nullptr, 0, InsertAtEnd) {
|
2011-07-26 07:16:38 +08:00
|
|
|
setOrdering(Ordering);
|
2017-07-12 06:23:00 +08:00
|
|
|
setSyncScopeID(SSID);
|
2011-07-26 07:16:38 +08:00
|
|
|
}
|
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// GetElementPtrInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-07-25 17:48:08 +08:00
|
|
|
void GetElementPtrInst::init(Value *Ptr, ArrayRef<Value *> IdxList,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name) {
|
2015-06-13 01:48:10 +08:00
|
|
|
assert(getNumOperands() == 1 + IdxList.size() &&
|
|
|
|
"NumOperands not initialized?");
|
2015-05-22 06:48:54 +08:00
|
|
|
Op<0>() = Ptr;
|
2011-07-25 17:48:08 +08:00
|
|
|
std::copy(IdxList.begin(), IdxList.end(), op_begin() + 1);
|
2008-06-05 00:14:12 +08:00
|
|
|
setName(Name);
|
2005-05-03 13:43:30 +08:00
|
|
|
}
|
|
|
|
|
2008-05-10 16:32:32 +08:00
|
|
|
GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI)
|
2015-05-06 02:03:48 +08:00
|
|
|
: Instruction(GEPI.getType(), GetElementPtr,
|
|
|
|
OperandTraits<GetElementPtrInst>::op_end(this) -
|
|
|
|
GEPI.getNumOperands(),
|
|
|
|
GEPI.getNumOperands()),
|
2015-06-01 11:09:34 +08:00
|
|
|
SourceElementType(GEPI.SourceElementType),
|
|
|
|
ResultElementType(GEPI.ResultElementType) {
|
2011-07-25 17:48:08 +08:00
|
|
|
std::copy(GEPI.op_begin(), GEPI.op_end(), op_begin());
|
2009-08-26 06:11:20 +08:00
|
|
|
SubclassOptionalData = GEPI.SubclassOptionalData;
|
2008-05-10 16:32:32 +08:00
|
|
|
}
|
|
|
|
|
2009-03-09 12:46:40 +08:00
|
|
|
/// 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.
|
|
|
|
///
|
2008-07-29 16:46:11 +08:00
|
|
|
template <typename IndexTy>
|
2015-03-31 05:41:43 +08:00
|
|
|
static Type *getIndexedTypeInternal(Type *Agg, ArrayRef<IndexTy> IdxList) {
|
2009-03-09 12:46:40 +08:00
|
|
|
// Handle the special case of the empty set index set, which is always valid.
|
2011-07-25 17:48:08 +08:00
|
|
|
if (IdxList.empty())
|
2008-05-16 03:50:34 +08:00
|
|
|
return Agg;
|
2011-12-05 14:29:09 +08:00
|
|
|
|
2009-03-09 12:46:40 +08:00
|
|
|
// If there is at least one index, the top level type must be sized, otherwise
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
// it cannot be 'stepped over'.
|
|
|
|
if (!Agg->isSized())
|
2014-04-09 14:08:46 +08:00
|
|
|
return nullptr;
|
2004-07-29 20:33:25 +08:00
|
|
|
|
2008-05-31 08:58:22 +08:00
|
|
|
unsigned CurIdx = 1;
|
2011-07-25 17:48:08 +08:00
|
|
|
for (; CurIdx != IdxList.size(); ++CurIdx) {
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
CompositeType *CT = dyn_cast<CompositeType>(Agg);
|
2014-04-09 14:08:46 +08:00
|
|
|
if (!CT || CT->isPointerTy()) return nullptr;
|
2011-07-25 17:48:08 +08:00
|
|
|
IndexTy Index = IdxList[CurIdx];
|
2014-04-09 14:08:46 +08:00
|
|
|
if (!CT->indexValid(Index)) return nullptr;
|
2008-05-31 08:58:22 +08:00
|
|
|
Agg = CT->getTypeAtIndex(Index);
|
|
|
|
}
|
2014-04-09 14:08:46 +08:00
|
|
|
return CurIdx == IdxList.size() ? Agg : nullptr;
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2015-03-31 05:41:43 +08:00
|
|
|
Type *GetElementPtrInst::getIndexedType(Type *Ty, ArrayRef<Value *> IdxList) {
|
|
|
|
return getIndexedTypeInternal(Ty, IdxList);
|
2011-01-14 16:07:43 +08:00
|
|
|
}
|
|
|
|
|
2015-03-31 05:41:43 +08:00
|
|
|
Type *GetElementPtrInst::getIndexedType(Type *Ty,
|
2011-07-25 17:48:08 +08:00
|
|
|
ArrayRef<Constant *> IdxList) {
|
2015-03-31 05:41:43 +08:00
|
|
|
return getIndexedTypeInternal(Ty, IdxList);
|
2008-07-29 16:46:11 +08:00
|
|
|
}
|
|
|
|
|
2015-03-31 05:41:43 +08:00
|
|
|
Type *GetElementPtrInst::getIndexedType(Type *Ty, ArrayRef<uint64_t> IdxList) {
|
|
|
|
return getIndexedTypeInternal(Ty, IdxList);
|
2005-05-03 13:43:30 +08:00
|
|
|
}
|
|
|
|
|
2007-04-14 08:12:57 +08:00
|
|
|
/// 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;
|
|
|
|
}
|
|
|
|
|
2007-04-28 04:35:56 +08:00
|
|
|
/// 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;
|
|
|
|
}
|
|
|
|
|
2009-09-08 07:54:19 +08:00
|
|
|
void GetElementPtrInst::setIsInBounds(bool B) {
|
|
|
|
cast<GEPOperator>(this)->setIsInBounds(B);
|
|
|
|
}
|
2007-04-14 08:12:57 +08:00
|
|
|
|
2009-09-28 05:33:04 +08:00
|
|
|
bool GetElementPtrInst::isInBounds() const {
|
|
|
|
return cast<GEPOperator>(this)->isInBounds();
|
|
|
|
}
|
|
|
|
|
2012-12-11 18:29:10 +08:00
|
|
|
bool GetElementPtrInst::accumulateConstantOffset(const DataLayout &DL,
|
|
|
|
APInt &Offset) const {
|
2012-12-11 19:05:15 +08:00
|
|
|
// Delegate to the generic GEPOperator implementation.
|
|
|
|
return cast<GEPOperator>(this)->accumulateConstantOffset(DL, Offset);
|
2012-12-11 18:29:10 +08:00
|
|
|
}
|
|
|
|
|
2006-01-11 03:05:34 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ExtractElementInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
ExtractElementInst::ExtractElementInst(Value *Val, Value *Index,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-04-08 09:18:18 +08:00
|
|
|
Instruction *InsertBef)
|
2007-02-15 10:26:10 +08:00
|
|
|
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
|
2008-05-10 16:32:32 +08:00
|
|
|
ExtractElement,
|
|
|
|
OperandTraits<ExtractElementInst>::op_begin(this),
|
|
|
|
2, InsertBef) {
|
2006-04-08 12:05:48 +08:00
|
|
|
assert(isValidOperands(Val, Index) &&
|
|
|
|
"Invalid extractelement instruction operands!");
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = Val;
|
|
|
|
Op<1>() = Index;
|
2007-02-24 08:55:48 +08:00
|
|
|
setName(Name);
|
2006-01-11 03:05:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ExtractElementInst::ExtractElementInst(Value *Val, Value *Index,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-04-08 09:18:18 +08:00
|
|
|
BasicBlock *InsertAE)
|
2007-02-15 10:26:10 +08:00
|
|
|
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
|
2008-05-10 16:32:32 +08:00
|
|
|
ExtractElement,
|
|
|
|
OperandTraits<ExtractElementInst>::op_begin(this),
|
|
|
|
2, InsertAE) {
|
2006-04-08 12:05:48 +08:00
|
|
|
assert(isValidOperands(Val, Index) &&
|
|
|
|
"Invalid extractelement instruction operands!");
|
|
|
|
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = Val;
|
|
|
|
Op<1>() = Index;
|
2007-02-24 08:55:48 +08:00
|
|
|
setName(Name);
|
2006-01-11 03:05:34 +08:00
|
|
|
}
|
|
|
|
|
2006-04-08 12:05:48 +08:00
|
|
|
bool ExtractElementInst::isValidOperands(const Value *Val, const Value *Index) {
|
[IR] Make {extract,insert}element accept an index of any integer type.
Given the following C code llvm currently generates suboptimal code for
x86-64:
__m128 bss4( const __m128 *ptr, size_t i, size_t j )
{
float f = ptr[i][j];
return (__m128) { f, f, f, f };
}
=================================================
define <4 x float> @_Z4bss4PKDv4_fmm(<4 x float>* nocapture readonly %ptr, i64 %i, i64 %j) #0 {
%a1 = getelementptr inbounds <4 x float>* %ptr, i64 %i
%a2 = load <4 x float>* %a1, align 16, !tbaa !1
%a3 = trunc i64 %j to i32
%a4 = extractelement <4 x float> %a2, i32 %a3
%a5 = insertelement <4 x float> undef, float %a4, i32 0
%a6 = insertelement <4 x float> %a5, float %a4, i32 1
%a7 = insertelement <4 x float> %a6, float %a4, i32 2
%a8 = insertelement <4 x float> %a7, float %a4, i32 3
ret <4 x float> %a8
}
=================================================
shlq $4, %rsi
addq %rdi, %rsi
movslq %edx, %rax
vbroadcastss (%rsi,%rax,4), %xmm0
retq
=================================================
The movslq is uneeded, but is present because of the trunc to i32 and then
sext back to i64 that the backend adds for vbroadcastss.
We can't remove it because it changes the meaning. The IR that clang
generates is already suboptimal. What clang really should emit is:
%a4 = extractelement <4 x float> %a2, i64 %j
This patch makes that legal. A separate patch will teach clang to do it.
Differential Revision: http://reviews.llvm.org/D3519
llvm-svn: 207801
2014-05-02 06:12:39 +08:00
|
|
|
if (!Val->getType()->isVectorTy() || !Index->getType()->isIntegerTy())
|
2006-04-08 12:05:48 +08:00
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-01-18 04:07:22 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// InsertElementInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2006-04-08 12:05:48 +08:00
|
|
|
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-04-08 09:18:18 +08:00
|
|
|
Instruction *InsertBef)
|
2008-05-10 16:32:32 +08:00
|
|
|
: Instruction(Vec->getType(), InsertElement,
|
|
|
|
OperandTraits<InsertElementInst>::op_begin(this),
|
|
|
|
3, InsertBef) {
|
2006-04-08 12:05:48 +08:00
|
|
|
assert(isValidOperands(Vec, Elt, Index) &&
|
|
|
|
"Invalid insertelement instruction operands!");
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = Vec;
|
|
|
|
Op<1>() = Elt;
|
|
|
|
Op<2>() = Index;
|
2007-02-24 08:55:48 +08:00
|
|
|
setName(Name);
|
2006-01-18 04:07:22 +08:00
|
|
|
}
|
|
|
|
|
2006-04-08 12:05:48 +08:00
|
|
|
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-04-08 09:18:18 +08:00
|
|
|
BasicBlock *InsertAE)
|
2008-05-10 16:32:32 +08:00
|
|
|
: Instruction(Vec->getType(), InsertElement,
|
|
|
|
OperandTraits<InsertElementInst>::op_begin(this),
|
|
|
|
3, InsertAE) {
|
2006-04-08 12:05:48 +08:00
|
|
|
assert(isValidOperands(Vec, Elt, Index) &&
|
|
|
|
"Invalid insertelement instruction operands!");
|
|
|
|
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = Vec;
|
|
|
|
Op<1>() = Elt;
|
|
|
|
Op<2>() = Index;
|
2007-02-24 08:55:48 +08:00
|
|
|
setName(Name);
|
2006-01-18 04:07:22 +08:00
|
|
|
}
|
|
|
|
|
2006-04-08 12:05:48 +08:00
|
|
|
bool InsertElementInst::isValidOperands(const Value *Vec, const Value *Elt,
|
|
|
|
const Value *Index) {
|
2010-02-16 19:11:14 +08:00
|
|
|
if (!Vec->getType()->isVectorTy())
|
2007-02-15 11:39:18 +08:00
|
|
|
return false; // First operand of insertelement must be vector type.
|
2006-04-08 12:05:48 +08:00
|
|
|
|
2007-02-15 10:26:10 +08:00
|
|
|
if (Elt->getType() != cast<VectorType>(Vec->getType())->getElementType())
|
2007-05-12 05:43:24 +08:00
|
|
|
return false;// Second operand of insertelement must be vector element type.
|
2006-04-08 12:05:48 +08:00
|
|
|
|
[IR] Make {extract,insert}element accept an index of any integer type.
Given the following C code llvm currently generates suboptimal code for
x86-64:
__m128 bss4( const __m128 *ptr, size_t i, size_t j )
{
float f = ptr[i][j];
return (__m128) { f, f, f, f };
}
=================================================
define <4 x float> @_Z4bss4PKDv4_fmm(<4 x float>* nocapture readonly %ptr, i64 %i, i64 %j) #0 {
%a1 = getelementptr inbounds <4 x float>* %ptr, i64 %i
%a2 = load <4 x float>* %a1, align 16, !tbaa !1
%a3 = trunc i64 %j to i32
%a4 = extractelement <4 x float> %a2, i32 %a3
%a5 = insertelement <4 x float> undef, float %a4, i32 0
%a6 = insertelement <4 x float> %a5, float %a4, i32 1
%a7 = insertelement <4 x float> %a6, float %a4, i32 2
%a8 = insertelement <4 x float> %a7, float %a4, i32 3
ret <4 x float> %a8
}
=================================================
shlq $4, %rsi
addq %rdi, %rsi
movslq %edx, %rax
vbroadcastss (%rsi,%rax,4), %xmm0
retq
=================================================
The movslq is uneeded, but is present because of the trunc to i32 and then
sext back to i64 that the backend adds for vbroadcastss.
We can't remove it because it changes the meaning. The IR that clang
generates is already suboptimal. What clang really should emit is:
%a4 = extractelement <4 x float> %a2, i64 %j
This patch makes that legal. A separate patch will teach clang to do it.
Differential Revision: http://reviews.llvm.org/D3519
llvm-svn: 207801
2014-05-02 06:12:39 +08:00
|
|
|
if (!Index->getType()->isIntegerTy())
|
2009-06-15 07:30:43 +08:00
|
|
|
return false; // Third operand of insertelement must be i32.
|
2006-04-08 12:05:48 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-04-08 09:18:18 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ShuffleVectorInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-04-08 09:18:18 +08:00
|
|
|
Instruction *InsertBefore)
|
2009-07-30 06:17:13 +08:00
|
|
|
: Instruction(VectorType::get(cast<VectorType>(V1->getType())->getElementType(),
|
2008-11-10 12:46:22 +08:00
|
|
|
cast<VectorType>(Mask->getType())->getNumElements()),
|
|
|
|
ShuffleVector,
|
|
|
|
OperandTraits<ShuffleVectorInst>::op_begin(this),
|
|
|
|
OperandTraits<ShuffleVectorInst>::operands(this),
|
|
|
|
InsertBefore) {
|
2006-04-08 09:18:18 +08:00
|
|
|
assert(isValidOperands(V1, V2, Mask) &&
|
|
|
|
"Invalid shuffle vector instruction operands!");
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = V1;
|
|
|
|
Op<1>() = V2;
|
|
|
|
Op<2>() = Mask;
|
2007-02-24 08:55:48 +08:00
|
|
|
setName(Name);
|
2006-04-08 09:18:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-04-08 09:18:18 +08:00
|
|
|
BasicBlock *InsertAtEnd)
|
2009-08-26 07:27:45 +08:00
|
|
|
: Instruction(VectorType::get(cast<VectorType>(V1->getType())->getElementType(),
|
|
|
|
cast<VectorType>(Mask->getType())->getNumElements()),
|
|
|
|
ShuffleVector,
|
|
|
|
OperandTraits<ShuffleVectorInst>::op_begin(this),
|
|
|
|
OperandTraits<ShuffleVectorInst>::operands(this),
|
|
|
|
InsertAtEnd) {
|
2006-04-08 09:18:18 +08:00
|
|
|
assert(isValidOperands(V1, V2, Mask) &&
|
|
|
|
"Invalid shuffle vector instruction operands!");
|
|
|
|
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = V1;
|
|
|
|
Op<1>() = V2;
|
|
|
|
Op<2>() = Mask;
|
2007-02-24 08:55:48 +08:00
|
|
|
setName(Name);
|
2006-04-08 09:18:18 +08:00
|
|
|
}
|
|
|
|
|
2008-11-10 12:46:22 +08:00
|
|
|
bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2,
|
2006-04-08 09:18:18 +08:00
|
|
|
const Value *Mask) {
|
2012-01-26 07:49:49 +08:00
|
|
|
// V1 and V2 must be vectors of the same type.
|
2010-02-16 19:11:14 +08:00
|
|
|
if (!V1->getType()->isVectorTy() || V1->getType() != V2->getType())
|
2008-03-02 13:28:33 +08:00
|
|
|
return false;
|
|
|
|
|
2012-01-26 07:49:49 +08:00
|
|
|
// Mask must be vector of i32.
|
2017-04-20 00:22:19 +08:00
|
|
|
auto *MaskTy = dyn_cast<VectorType>(Mask->getType());
|
2014-04-09 14:08:46 +08:00
|
|
|
if (!MaskTy || !MaskTy->getElementType()->isIntegerTy(32))
|
2006-04-08 09:18:18 +08:00
|
|
|
return false;
|
2010-08-13 08:16:46 +08:00
|
|
|
|
|
|
|
// Check to see if Mask is valid.
|
2012-01-26 07:49:49 +08:00
|
|
|
if (isa<UndefValue>(Mask) || isa<ConstantAggregateZero>(Mask))
|
|
|
|
return true;
|
|
|
|
|
2017-04-20 00:22:19 +08:00
|
|
|
if (const auto *MV = dyn_cast<ConstantVector>(Mask)) {
|
2012-01-26 07:49:49 +08:00
|
|
|
unsigned V1Size = cast<VectorType>(V1->getType())->getNumElements();
|
2014-03-10 23:03:06 +08:00
|
|
|
for (Value *Op : MV->operands()) {
|
2017-04-20 00:22:19 +08:00
|
|
|
if (auto *CI = dyn_cast<ConstantInt>(Op)) {
|
2012-01-26 07:49:49 +08:00
|
|
|
if (CI->uge(V1Size*2))
|
2010-08-13 08:16:46 +08:00
|
|
|
return false;
|
2014-03-10 23:03:06 +08:00
|
|
|
} else if (!isa<UndefValue>(Op)) {
|
2010-08-13 08:16:46 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2012-01-26 07:49:49 +08:00
|
|
|
return true;
|
2011-10-26 08:34:48 +08:00
|
|
|
}
|
2012-01-26 07:49:49 +08:00
|
|
|
|
2017-04-20 00:22:19 +08:00
|
|
|
if (const auto *CDS = dyn_cast<ConstantDataSequential>(Mask)) {
|
2012-01-26 07:49:49 +08:00
|
|
|
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.
|
2017-04-20 00:22:19 +08:00
|
|
|
if (const auto *CE = dyn_cast<ConstantExpr>(Mask))
|
2012-01-26 07:49:49 +08:00
|
|
|
if (CE->getOpcode() == Instruction::UserOp1)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
2006-04-08 09:18:18 +08:00
|
|
|
}
|
|
|
|
|
2012-01-26 10:51:13 +08:00
|
|
|
int ShuffleVectorInst::getMaskValue(Constant *Mask, unsigned i) {
|
|
|
|
assert(i < Mask->getType()->getVectorNumElements() && "Index out of range");
|
2017-04-20 00:22:19 +08:00
|
|
|
if (auto *CDS = dyn_cast<ConstantDataSequential>(Mask))
|
2012-01-26 07:49:49 +08:00
|
|
|
return CDS->getElementAsInteger(i);
|
2012-01-26 10:51:13 +08:00
|
|
|
Constant *C = Mask->getAggregateElement(i);
|
2012-01-26 07:49:49 +08:00
|
|
|
if (isa<UndefValue>(C))
|
2008-03-02 13:28:33 +08:00
|
|
|
return -1;
|
2012-01-26 07:49:49 +08:00
|
|
|
return cast<ConstantInt>(C)->getZExtValue();
|
2008-03-02 13:28:33 +08:00
|
|
|
}
|
|
|
|
|
2012-01-26 10:51:13 +08:00
|
|
|
void ShuffleVectorInst::getShuffleMask(Constant *Mask,
|
|
|
|
SmallVectorImpl<int> &Result) {
|
|
|
|
unsigned NumElts = Mask->getType()->getVectorNumElements();
|
2012-01-26 07:49:49 +08:00
|
|
|
|
2017-04-20 00:22:19 +08:00
|
|
|
if (auto *CDS = dyn_cast<ConstantDataSequential>(Mask)) {
|
2012-01-26 07:49:49 +08:00
|
|
|
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 :
|
2012-01-26 08:41:50 +08:00
|
|
|
cast<ConstantInt>(C)->getZExtValue());
|
2012-01-26 07:49:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-23 08:36:11 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// InsertValueInst Class
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-07-13 18:26:04 +08:00
|
|
|
void InsertValueInst::init(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
|
|
|
|
const Twine &Name) {
|
2015-06-13 01:48:10 +08:00
|
|
|
assert(getNumOperands() == 2 && "NumOperands not initialized?");
|
2008-05-23 08:36:11 +08:00
|
|
|
|
2011-07-13 18:26:04 +08:00
|
|
|
// 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.
|
2017-05-16 05:57:41 +08:00
|
|
|
assert(!Idxs.empty() && "InsertValueInst must have at least one index");
|
2008-05-23 08:36:11 +08:00
|
|
|
|
2011-07-13 18:26:04 +08:00
|
|
|
assert(ExtractValueInst::getIndexedType(Agg->getType(), Idxs) ==
|
|
|
|
Val->getType() && "Inserted value must match indexed type!");
|
2008-05-31 08:58:22 +08:00
|
|
|
Op<0>() = Agg;
|
|
|
|
Op<1>() = Val;
|
|
|
|
|
2011-07-13 18:26:04 +08:00
|
|
|
Indices.append(Idxs.begin(), Idxs.end());
|
2008-06-04 22:40:55 +08:00
|
|
|
setName(Name);
|
2008-05-23 08:36:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
InsertValueInst::InsertValueInst(const InsertValueInst &IVI)
|
2008-05-27 19:03:29 +08:00
|
|
|
: Instruction(IVI.getType(), InsertValue,
|
2008-05-31 08:58:22 +08:00
|
|
|
OperandTraits<InsertValueInst>::op_begin(this), 2),
|
|
|
|
Indices(IVI.Indices) {
|
2008-06-18 07:25:49 +08:00
|
|
|
Op<0>() = IVI.getOperand(0);
|
|
|
|
Op<1>() = IVI.getOperand(1);
|
2009-08-26 06:11:20 +08:00
|
|
|
SubclassOptionalData = IVI.SubclassOptionalData;
|
2008-05-23 08:36:11 +08:00
|
|
|
}
|
|
|
|
|
2008-05-16 03:50:34 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ExtractValueInst Class
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-07-13 18:26:04 +08:00
|
|
|
void ExtractValueInst::init(ArrayRef<unsigned> Idxs, const Twine &Name) {
|
2015-06-13 01:48:10 +08:00
|
|
|
assert(getNumOperands() == 1 && "NumOperands not initialized?");
|
2008-05-23 08:36:11 +08:00
|
|
|
|
2011-07-13 18:26:04 +08:00
|
|
|
// There's no fundamental reason why we require at least one index.
|
|
|
|
// But there's no present need to support it.
|
2017-05-16 05:57:41 +08:00
|
|
|
assert(!Idxs.empty() && "ExtractValueInst must have at least one index");
|
2008-05-31 08:58:22 +08:00
|
|
|
|
2011-07-13 18:26:04 +08:00
|
|
|
Indices.append(Idxs.begin(), Idxs.end());
|
2008-06-04 22:40:55 +08:00
|
|
|
setName(Name);
|
2008-05-23 08:36:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
|
2008-06-07 04:28:12 +08:00
|
|
|
: UnaryInstruction(EVI.getType(), ExtractValue, EVI.getOperand(0)),
|
2008-05-31 08:58:22 +08:00
|
|
|
Indices(EVI.Indices) {
|
2009-08-26 06:11:20 +08:00
|
|
|
SubclassOptionalData = EVI.SubclassOptionalData;
|
2008-05-23 08:36:11 +08:00
|
|
|
}
|
|
|
|
|
2008-05-16 03:50:34 +08:00
|
|
|
// 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.
|
|
|
|
//
|
2011-07-18 12:54:35 +08:00
|
|
|
Type *ExtractValueInst::getIndexedType(Type *Agg,
|
2011-07-13 18:26:04 +08:00
|
|
|
ArrayRef<unsigned> Idxs) {
|
2014-03-10 23:03:06 +08:00
|
|
|
for (unsigned Index : Idxs) {
|
2010-12-06 04:50:26 +08:00
|
|
|
// 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.
|
2011-07-18 12:54:35 +08:00
|
|
|
if (ArrayType *AT = dyn_cast<ArrayType>(Agg)) {
|
2010-12-06 04:50:26 +08:00
|
|
|
if (Index >= AT->getNumElements())
|
2014-04-09 14:08:46 +08:00
|
|
|
return nullptr;
|
2011-07-18 12:54:35 +08:00
|
|
|
} else if (StructType *ST = dyn_cast<StructType>(Agg)) {
|
2010-12-06 04:50:26 +08:00
|
|
|
if (Index >= ST->getNumElements())
|
2014-04-09 14:08:46 +08:00
|
|
|
return nullptr;
|
2010-12-06 04:50:26 +08:00
|
|
|
} else {
|
|
|
|
// Not a valid type to index into.
|
2014-04-09 14:08:46 +08:00
|
|
|
return nullptr;
|
2010-12-06 04:50:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Agg = cast<CompositeType>(Agg)->getTypeAtIndex(Index);
|
2008-05-16 03:50:34 +08:00
|
|
|
}
|
Land the long talked about "type system rewrite" patch. This
patch brings numerous advantages to LLVM. One way to look at it
is through diffstat:
109 files changed, 3005 insertions(+), 5906 deletions(-)
Removing almost 3K lines of code is a good thing. Other advantages
include:
1. Value::getType() is a simple load that can be CSE'd, not a mutating
union-find operation.
2. Types a uniqued and never move once created, defining away PATypeHolder.
3. Structs can be "named" now, and their name is part of the identity that
uniques them. This means that the compiler doesn't merge them structurally
which makes the IR much less confusing.
4. Now that there is no way to get a cycle in a type graph without a named
struct type, "upreferences" go away.
5. Type refinement is completely gone, which should make LTO much MUCH faster
in some common cases with C++ code.
6. Types are now generally immutable, so we can use "Type *" instead
"const Type *" everywhere.
Downsides of this patch are that it removes some functions from the C API,
so people using those will have to upgrade to (not yet added) new API.
"LLVM 3.0" is the right time to do this.
There are still some cleanups pending after this, this patch is large enough
as-is.
llvm-svn: 134829
2011-07-10 01:41:24 +08:00
|
|
|
return const_cast<Type*>(Agg);
|
2008-05-16 03:50:34 +08:00
|
|
|
}
|
2006-04-08 09:18:18 +08:00
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// BinaryOperator Class
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2007-02-24 08:55:48 +08:00
|
|
|
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
|
2011-07-18 12:54:35 +08:00
|
|
|
Type *Ty, const Twine &Name,
|
2007-02-24 08:55:48 +08:00
|
|
|
Instruction *InsertBefore)
|
2010-05-04 06:44:19 +08:00
|
|
|
: Instruction(Ty, iType,
|
2008-05-10 16:32:32 +08:00
|
|
|
OperandTraits<BinaryOperator>::op_begin(this),
|
|
|
|
OperandTraits<BinaryOperator>::operands(this),
|
|
|
|
InsertBefore) {
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = S1;
|
|
|
|
Op<1>() = S2;
|
2007-02-24 08:55:48 +08:00
|
|
|
setName(Name);
|
2017-06-26 15:15:59 +08:00
|
|
|
AssertOK();
|
2007-02-24 08:55:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
|
2011-07-18 12:54:35 +08:00
|
|
|
Type *Ty, const Twine &Name,
|
2007-02-24 08:55:48 +08:00
|
|
|
BasicBlock *InsertAtEnd)
|
2010-05-04 06:44:19 +08:00
|
|
|
: Instruction(Ty, iType,
|
2008-05-10 16:32:32 +08:00
|
|
|
OperandTraits<BinaryOperator>::op_begin(this),
|
|
|
|
OperandTraits<BinaryOperator>::operands(this),
|
|
|
|
InsertAtEnd) {
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = S1;
|
|
|
|
Op<1>() = S2;
|
2007-02-24 08:55:48 +08:00
|
|
|
setName(Name);
|
2017-06-26 15:15:59 +08:00
|
|
|
AssertOK();
|
2007-02-24 08:55:48 +08:00
|
|
|
}
|
|
|
|
|
2017-06-26 15:15:59 +08:00
|
|
|
void BinaryOperator::AssertOK() {
|
2005-01-29 08:35:16 +08:00
|
|
|
Value *LHS = getOperand(0), *RHS = getOperand(1);
|
2010-12-23 08:58:24 +08:00
|
|
|
(void)LHS; (void)RHS; // Silence warnings.
|
2005-01-29 08:35:16 +08:00
|
|
|
assert(LHS->getType() == RHS->getType() &&
|
|
|
|
"Binary operator operand types must match!");
|
2004-07-29 20:33:25 +08:00
|
|
|
#ifndef NDEBUG
|
2017-06-26 15:15:59 +08:00
|
|
|
switch (getOpcode()) {
|
2004-07-29 20:33:25 +08:00
|
|
|
case Add: case Sub:
|
2009-06-05 06:49:04 +08:00
|
|
|
case Mul:
|
|
|
|
assert(getType() == LHS->getType() &&
|
|
|
|
"Arithmetic operation should return same type as operands!");
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(getType()->isIntOrIntVectorTy() &&
|
2009-06-05 06:49:04 +08:00
|
|
|
"Tried to create an integer operation on a non-integer type!");
|
|
|
|
break;
|
|
|
|
case FAdd: case FSub:
|
|
|
|
case FMul:
|
2005-01-29 08:35:16 +08:00
|
|
|
assert(getType() == LHS->getType() &&
|
2004-07-29 20:33:25 +08:00
|
|
|
"Arithmetic operation should return same type as operands!");
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(getType()->isFPOrFPVectorTy() &&
|
2009-06-05 06:49:04 +08:00
|
|
|
"Tried to create a floating-point operation on a "
|
|
|
|
"non-floating-point type!");
|
2004-07-29 20:33:25 +08:00
|
|
|
break;
|
2006-10-26 14:15:43 +08:00
|
|
|
case UDiv:
|
|
|
|
case SDiv:
|
|
|
|
assert(getType() == LHS->getType() &&
|
|
|
|
"Arithmetic operation should return same type as operands!");
|
2017-06-26 01:33:48 +08:00
|
|
|
assert(getType()->isIntOrIntVectorTy() &&
|
2006-10-26 14:15:43 +08:00
|
|
|
"Incorrect operand type (not integer) for S/UDIV");
|
|
|
|
break;
|
|
|
|
case FDiv:
|
|
|
|
assert(getType() == LHS->getType() &&
|
|
|
|
"Arithmetic operation should return same type as operands!");
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(getType()->isFPOrFPVectorTy() &&
|
2009-06-16 06:25:12 +08:00
|
|
|
"Incorrect operand type (not floating point) for FDIV");
|
2006-10-26 14:15:43 +08:00
|
|
|
break;
|
2006-11-02 09:53:59 +08:00
|
|
|
case URem:
|
|
|
|
case SRem:
|
|
|
|
assert(getType() == LHS->getType() &&
|
|
|
|
"Arithmetic operation should return same type as operands!");
|
2017-06-26 01:33:48 +08:00
|
|
|
assert(getType()->isIntOrIntVectorTy() &&
|
2006-11-02 09:53:59 +08:00
|
|
|
"Incorrect operand type (not integer) for S/UREM");
|
|
|
|
break;
|
|
|
|
case FRem:
|
|
|
|
assert(getType() == LHS->getType() &&
|
|
|
|
"Arithmetic operation should return same type as operands!");
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(getType()->isFPOrFPVectorTy() &&
|
2009-06-16 06:25:12 +08:00
|
|
|
"Incorrect operand type (not floating point) for FREM");
|
2006-11-02 09:53:59 +08:00
|
|
|
break;
|
2007-02-02 10:16:23 +08:00
|
|
|
case Shl:
|
|
|
|
case LShr:
|
|
|
|
case AShr:
|
|
|
|
assert(getType() == LHS->getType() &&
|
|
|
|
"Shift operation should return same type as operands!");
|
2017-06-26 01:33:48 +08:00
|
|
|
assert(getType()->isIntOrIntVectorTy() &&
|
2008-07-29 23:49:41 +08:00
|
|
|
"Tried to create a shift operation on a non-integral type!");
|
2007-02-02 10:16:23 +08:00
|
|
|
break;
|
2004-07-29 20:33:25 +08:00
|
|
|
case And: case Or:
|
|
|
|
case Xor:
|
2005-01-29 08:35:16 +08:00
|
|
|
assert(getType() == LHS->getType() &&
|
2004-07-29 20:33:25 +08:00
|
|
|
"Logical operation should return same type as operands!");
|
2017-06-26 01:33:48 +08:00
|
|
|
assert(getType()->isIntOrIntVectorTy() &&
|
2005-01-27 14:46:38 +08:00
|
|
|
"Tried to create a logical operation on a non-integral type!");
|
2004-07-29 20:33:25 +08:00
|
|
|
break;
|
2017-06-26 15:15:59 +08:00
|
|
|
default: llvm_unreachable("Invalid opcode provided");
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2008-05-17 03:29:10 +08:00
|
|
|
BinaryOperator *BinaryOperator::Create(BinaryOps Op, Value *S1, Value *S2,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2004-07-29 20:33:25 +08:00
|
|
|
Instruction *InsertBefore) {
|
|
|
|
assert(S1->getType() == S2->getType() &&
|
|
|
|
"Cannot create binary operator with two operands of differing type!");
|
2006-12-23 14:05:41 +08:00
|
|
|
return new BinaryOperator(Op, S1, S2, S1->getType(), Name, InsertBefore);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2008-05-17 03:29:10 +08:00
|
|
|
BinaryOperator *BinaryOperator::Create(BinaryOps Op, Value *S1, Value *S2,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2004-07-29 20:33:25 +08:00
|
|
|
BasicBlock *InsertAtEnd) {
|
2008-05-17 03:29:10 +08:00
|
|
|
BinaryOperator *Res = Create(Op, S1, S2, Name);
|
2004-07-29 20:33:25 +08:00
|
|
|
InsertAtEnd->getInstList().push_back(Res);
|
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
|
2009-08-13 00:23:25 +08:00
|
|
|
BinaryOperator *BinaryOperator::CreateNeg(Value *Op, const Twine &Name,
|
2004-07-29 20:33:25 +08:00
|
|
|
Instruction *InsertBefore) {
|
2009-07-28 04:59:43 +08:00
|
|
|
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
|
2007-01-21 08:29:26 +08:00
|
|
|
return new BinaryOperator(Instruction::Sub,
|
|
|
|
zero, Op,
|
|
|
|
Op->getType(), Name, InsertBefore);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2009-08-13 00:23:25 +08:00
|
|
|
BinaryOperator *BinaryOperator::CreateNeg(Value *Op, const Twine &Name,
|
2004-07-29 20:33:25 +08:00
|
|
|
BasicBlock *InsertAtEnd) {
|
2009-07-28 04:59:43 +08:00
|
|
|
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
|
2007-01-21 08:29:26 +08:00
|
|
|
return new BinaryOperator(Instruction::Sub,
|
|
|
|
zero, Op,
|
|
|
|
Op->getType(), Name, InsertAtEnd);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2009-12-18 10:58:50 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2010-02-02 20:53:04 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2009-08-13 00:23:25 +08:00
|
|
|
BinaryOperator *BinaryOperator::CreateFNeg(Value *Op, const Twine &Name,
|
2009-06-05 06:49:04 +08:00
|
|
|
Instruction *InsertBefore) {
|
2009-07-28 04:59:43 +08:00
|
|
|
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
|
2012-01-25 14:02:56 +08:00
|
|
|
return new BinaryOperator(Instruction::FSub, zero, Op,
|
2009-06-05 06:49:04 +08:00
|
|
|
Op->getType(), Name, InsertBefore);
|
|
|
|
}
|
|
|
|
|
2009-08-13 00:23:25 +08:00
|
|
|
BinaryOperator *BinaryOperator::CreateFNeg(Value *Op, const Twine &Name,
|
2009-06-05 06:49:04 +08:00
|
|
|
BasicBlock *InsertAtEnd) {
|
2009-07-28 04:59:43 +08:00
|
|
|
Value *zero = ConstantFP::getZeroValueForNegation(Op->getType());
|
2012-01-25 14:02:56 +08:00
|
|
|
return new BinaryOperator(Instruction::FSub, zero, Op,
|
2009-06-05 06:49:04 +08:00
|
|
|
Op->getType(), Name, InsertAtEnd);
|
|
|
|
}
|
|
|
|
|
2009-08-13 00:23:25 +08:00
|
|
|
BinaryOperator *BinaryOperator::CreateNot(Value *Op, const Twine &Name,
|
2004-07-29 20:33:25 +08:00
|
|
|
Instruction *InsertBefore) {
|
2012-01-25 14:02:56 +08:00
|
|
|
Constant *C = Constant::getAllOnesValue(Op->getType());
|
2006-03-26 05:54:21 +08:00
|
|
|
return new BinaryOperator(Instruction::Xor, Op, C,
|
2004-07-29 20:33:25 +08:00
|
|
|
Op->getType(), Name, InsertBefore);
|
|
|
|
}
|
|
|
|
|
2009-08-13 00:23:25 +08:00
|
|
|
BinaryOperator *BinaryOperator::CreateNot(Value *Op, const Twine &Name,
|
2004-07-29 20:33:25 +08:00
|
|
|
BasicBlock *InsertAtEnd) {
|
2012-01-25 14:02:56 +08:00
|
|
|
Constant *AllOnes = Constant::getAllOnesValue(Op->getType());
|
2005-12-22 02:22:19 +08:00
|
|
|
return new BinaryOperator(Instruction::Xor, Op, AllOnes,
|
2004-07-29 20:33:25 +08:00
|
|
|
Op->getType(), Name, InsertAtEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
// isConstantAllOnes - Helper function for several functions below
|
|
|
|
static inline bool isConstantAllOnes(const Value *V) {
|
2012-01-27 11:08:05 +08:00
|
|
|
if (const Constant *C = dyn_cast<Constant>(V))
|
|
|
|
return C->isAllOnesValue();
|
2007-06-15 14:04:24 +08:00
|
|
|
return false;
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2009-07-14 06:18:28 +08:00
|
|
|
bool BinaryOperator::isNeg(const Value *V) {
|
2004-07-29 20:33:25 +08:00
|
|
|
if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V))
|
|
|
|
if (Bop->getOpcode() == Instruction::Sub)
|
2016-02-04 05:34:39 +08:00
|
|
|
if (Constant *C = dyn_cast<Constant>(Bop->getOperand(0)))
|
2009-07-14 06:18:28 +08:00
|
|
|
return C->isNegativeZeroValue();
|
2004-07-29 20:33:25 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-01-09 08:13:41 +08:00
|
|
|
bool BinaryOperator::isFNeg(const Value *V, bool IgnoreZeroSign) {
|
2009-06-05 06:49:04 +08:00
|
|
|
if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V))
|
|
|
|
if (Bop->getOpcode() == Instruction::FSub)
|
2016-02-04 05:34:39 +08:00
|
|
|
if (Constant *C = dyn_cast<Constant>(Bop->getOperand(0))) {
|
2013-01-09 08:13:41 +08:00
|
|
|
if (!IgnoreZeroSign)
|
|
|
|
IgnoreZeroSign = cast<Instruction>(V)->hasNoSignedZeros();
|
|
|
|
return !IgnoreZeroSign ? C->isNegativeZeroValue() : C->isZeroValue();
|
|
|
|
}
|
2009-06-05 06:49:04 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2005-04-24 15:28:37 +08:00
|
|
|
Value *BinaryOperator::getNegArgument(Value *BinOp) {
|
|
|
|
return cast<BinaryOperator>(BinOp)->getOperand(1);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2005-04-24 15:28:37 +08:00
|
|
|
const Value *BinaryOperator::getNegArgument(const Value *BinOp) {
|
|
|
|
return getNegArgument(const_cast<Value*>(BinOp));
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2009-06-05 06:49:04 +08:00
|
|
|
Value *BinaryOperator::getFNegArgument(Value *BinOp) {
|
|
|
|
return cast<BinaryOperator>(BinOp)->getOperand(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
const Value *BinaryOperator::getFNegArgument(const Value *BinOp) {
|
|
|
|
return getFNegArgument(const_cast<Value*>(BinOp));
|
|
|
|
}
|
|
|
|
|
2005-04-24 15:28:37 +08:00
|
|
|
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);
|
2004-07-29 20:33:25 +08:00
|
|
|
if (isConstantAllOnes(Op0)) return Op1;
|
|
|
|
|
|
|
|
assert(isConstantAllOnes(Op1));
|
|
|
|
return Op0;
|
|
|
|
}
|
|
|
|
|
2005-04-24 15:28:37 +08:00
|
|
|
const Value *BinaryOperator::getNotArgument(const Value *BinOp) {
|
|
|
|
return getNotArgument(const_cast<Value*>(BinOp));
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2016-11-17 02:09:44 +08:00
|
|
|
// 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.
|
2004-07-29 20:33:25 +08:00
|
|
|
bool BinaryOperator::swapOperands() {
|
2006-12-23 14:05:41 +08:00
|
|
|
if (!isCommutative())
|
|
|
|
return true; // Can't commute operands
|
2008-05-14 06:51:52 +08:00
|
|
|
Op<0>().swap(Op<1>());
|
2004-07-29 20:33:25 +08:00
|
|
|
return false;
|
2006-09-18 03:29:56 +08:00
|
|
|
}
|
|
|
|
|
2012-04-17 00:28:59 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// FPMathOperator Class
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
float FPMathOperator::getFPAccuracy() const {
|
2014-11-12 05:30:22 +08:00
|
|
|
const MDNode *MD =
|
|
|
|
cast<Instruction>(this)->getMetadata(LLVMContext::MD_fpmath);
|
2012-04-17 00:28:59 +08:00
|
|
|
if (!MD)
|
|
|
|
return 0.0;
|
IR: Split Metadata from Value
Split `Metadata` away from the `Value` class hierarchy, as part of
PR21532. Assembly and bitcode changes are in the wings, but this is the
bulk of the change for the IR C++ API.
I have a follow-up patch prepared for `clang`. If this breaks other
sub-projects, I apologize in advance :(. Help me compile it on Darwin
I'll try to fix it. FWIW, the errors should be easy to fix, so it may
be simpler to just fix it yourself.
This breaks the build for all metadata-related code that's out-of-tree.
Rest assured the transition is mechanical and the compiler should catch
almost all of the problems.
Here's a quick guide for updating your code:
- `Metadata` is the root of a class hierarchy with three main classes:
`MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
the `Value` class hierarchy. It is typeless -- i.e., instances do
*not* have a `Type`.
- `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
- `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
If you're referring solely to resolved `MDNode`s -- post graph
construction -- just use `MDNode*`.
- `MDNode` (and the rest of `Metadata`) have only limited support for
`replaceAllUsesWith()`.
As long as an `MDNode` is pointing at a forward declaration -- the
result of `MDNode::getTemporary()` -- it maintains a side map of its
uses and can RAUW itself. Once the forward declarations are fully
resolved RAUW support is dropped on the ground. This means that
uniquing collisions on changing operands cause nodes to become
"distinct". (This already happened fairly commonly, whenever an
operand went to null.)
If you're constructing complex (non self-reference) `MDNode` cycles,
you need to call `MDNode::resolveCycles()` on each node (or on a
top-level node that somehow references all of the nodes). Also,
don't do that. Metadata cycles (and the RAUW machinery needed to
construct them) are expensive.
- An `MDNode` can only refer to a `Constant` through a bridge called
`ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
As a side effect, accessing an operand of an `MDNode` that is known
to be, e.g., `ConstantInt`, takes three steps: first, cast from
`Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
third, cast down to `ConstantInt`.
The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
metadata schema owners transition away from using `Constant`s when
the type isn't important (and they don't care about referring to
`GlobalValue`s).
In the meantime, I've added transitional API to the `mdconst`
namespace that matches semantics with the old code, in order to
avoid adding the error-prone three-step equivalent to every call
site. If your old code was:
MDNode *N = foo();
bar(isa <ConstantInt>(N->getOperand(0)));
baz(cast <ConstantInt>(N->getOperand(1)));
bak(cast_or_null <ConstantInt>(N->getOperand(2)));
bat(dyn_cast <ConstantInt>(N->getOperand(3)));
bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
you can trivially match its semantics with:
MDNode *N = foo();
bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
and when you transition your metadata schema to `MDInt`:
MDNode *N = foo();
bar(isa <MDInt>(N->getOperand(0)));
baz(cast <MDInt>(N->getOperand(1)));
bak(cast_or_null <MDInt>(N->getOperand(2)));
bat(dyn_cast <MDInt>(N->getOperand(3)));
bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
- A `CallInst` -- specifically, intrinsic instructions -- can refer to
metadata through a bridge called `MetadataAsValue`. This is a
subclass of `Value` where `getType()->isMetadataTy()`.
`MetadataAsValue` is the *only* class that can legally refer to a
`LocalAsMetadata`, which is a bridged form of non-`Constant` values
like `Argument` and `Instruction`. It can also refer to any other
`Metadata` subclass.
(I'll break all your testcases in a follow-up commit, when I propagate
this change to assembly.)
llvm-svn: 223802
2014-12-10 02:38:53 +08:00
|
|
|
ConstantFP *Accuracy = mdconst::extract<ConstantFP>(MD->getOperand(0));
|
2012-04-17 03:39:33 +08:00
|
|
|
return Accuracy->getValueAPF().convertToFloat();
|
2012-04-17 00:28:59 +08:00
|
|
|
}
|
|
|
|
|
2006-09-18 12:54:57 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CastInst Class
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2006-11-27 09:05:10 +08:00
|
|
|
// 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:
|
2010-02-16 00:12:20 +08:00
|
|
|
return getOperand(0)->getType()->isIntegerTy() &&
|
|
|
|
getType()->isIntegerTy();
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CastInst::isLosslessCast() const {
|
|
|
|
// Only BitCast can be lossless, exit fast if we're not BitCast
|
|
|
|
if (getOpcode() != Instruction::BitCast)
|
2006-09-18 12:54:57 +08:00
|
|
|
return false;
|
|
|
|
|
2006-11-27 09:05:10 +08:00
|
|
|
// Identity cast is always lossless
|
2016-02-04 05:34:39 +08:00
|
|
|
Type *SrcTy = getOperand(0)->getType();
|
|
|
|
Type *DstTy = getType();
|
2006-11-27 09:05:10 +08:00
|
|
|
if (SrcTy == DstTy)
|
|
|
|
return true;
|
|
|
|
|
2006-12-31 13:26:44 +08:00
|
|
|
// Pointer to pointer is always lossless.
|
2010-02-16 19:11:14 +08:00
|
|
|
if (SrcTy->isPointerTy())
|
|
|
|
return DstTy->isPointerTy();
|
2006-11-27 09:05:10 +08:00
|
|
|
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:
|
2008-05-13 00:34:30 +08:00
|
|
|
/// # bitcast i32* %x to i8*
|
|
|
|
/// # bitcast <2 x i32> %x to <4 x i16>
|
|
|
|
/// # ptrtoint i32* %x to i32 ; on 32-bit plaforms only
|
2010-05-29 05:41:37 +08:00
|
|
|
/// @brief Determine if the described cast is a no-op.
|
|
|
|
bool CastInst::isNoopCast(Instruction::CastOps Opcode,
|
2011-07-18 12:54:35 +08:00
|
|
|
Type *SrcTy,
|
|
|
|
Type *DestTy,
|
2017-10-05 15:07:09 +08:00
|
|
|
const DataLayout &DL) {
|
2010-05-29 05:41:37 +08:00
|
|
|
switch (Opcode) {
|
2012-02-06 06:14:15 +08:00
|
|
|
default: llvm_unreachable("Invalid CastOp");
|
2006-11-27 09:05:10 +08:00
|
|
|
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:
|
2013-11-15 09:34:59 +08:00
|
|
|
case Instruction::AddrSpaceCast:
|
|
|
|
// TODO: Target informations may give a more accurate answer here.
|
|
|
|
return false;
|
2006-11-27 09:05:10 +08:00
|
|
|
case Instruction::BitCast:
|
|
|
|
return true; // BitCast never modifies bits.
|
|
|
|
case Instruction::PtrToInt:
|
2017-10-05 15:07:09 +08:00
|
|
|
return DL.getIntPtrType(SrcTy)->getScalarSizeInBits() ==
|
2010-05-29 05:41:37 +08:00
|
|
|
DestTy->getScalarSizeInBits();
|
2006-11-27 09:05:10 +08:00
|
|
|
case Instruction::IntToPtr:
|
2017-10-05 15:07:09 +08:00
|
|
|
return DL.getIntPtrType(DestTy)->getScalarSizeInBits() ==
|
2010-05-29 05:41:37 +08:00
|
|
|
SrcTy->getScalarSizeInBits();
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
bool CastInst::isNoopCast(const DataLayout &DL) const {
|
2017-10-03 14:03:49 +08:00
|
|
|
return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), DL);
|
2014-03-07 01:33:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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
|
2006-11-27 09:05:10 +08:00
|
|
|
/// 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
|
2015-12-12 02:12:01 +08:00
|
|
|
/// If no such cast is permitted, the function returns 0.
|
2006-11-27 09:05:10 +08:00
|
|
|
unsigned CastInst::isEliminableCastPair(
|
|
|
|
Instruction::CastOps firstOp, Instruction::CastOps secondOp,
|
2012-10-31 00:03:32 +08:00
|
|
|
Type *SrcTy, Type *MidTy, Type *DstTy, Type *SrcIntPtrTy, Type *MidIntPtrTy,
|
|
|
|
Type *DstIntPtrTy) {
|
2006-11-27 09:05:10 +08:00
|
|
|
// 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
|
2015-12-12 02:12:01 +08:00
|
|
|
// correspond to secondOp. In looking at the table below, keep in mind
|
2006-11-27 09:05:10 +08:00
|
|
|
// 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
|
2013-11-15 09:34:59 +08:00
|
|
|
// 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
|
2006-11-27 09:05:10 +08:00
|
|
|
// PTRTOINT n/a Pointer n/a Integral Unsigned
|
|
|
|
// INTTOPTR n/a Integral Unsigned Pointer n/a
|
2013-11-15 09:34:59 +08:00
|
|
|
// BITCAST = FirstClass n/a FirstClass n/a
|
|
|
|
// ADDRSPCST n/a Pointer n/a Pointer n/a
|
2006-12-06 07:43:59 +08:00
|
|
|
//
|
|
|
|
// NOTE: some transforms are safe, but we consider them to be non-profitable.
|
2009-06-15 07:30:43 +08:00
|
|
|
// 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
|
2013-11-15 09:34:59 +08:00
|
|
|
// of the produced value (we no longer know the top-part is all zeros).
|
2006-12-06 07:43:59 +08:00
|
|
|
// Further this conversion is often much more expensive for typical hardware,
|
2013-11-15 09:34:59 +08:00
|
|
|
// and causes issues when building libgcc. We disallow fptosi+sext for the
|
2006-12-06 07:43:59 +08:00
|
|
|
// same reason.
|
2013-11-15 09:34:59 +08:00
|
|
|
const unsigned numCastOps =
|
2006-11-27 09:05:10 +08:00
|
|
|
Instruction::CastOpsEnd - Instruction::CastOpsBegin;
|
|
|
|
static const uint8_t CastResults[numCastOps][numCastOps] = {
|
2013-11-15 09:34:59 +08:00
|
|
|
// 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 -+
|
2015-04-21 08:05:41 +08:00
|
|
|
{ 8, 1, 9,99,99, 2,17,99,99,99, 2, 3, 0}, // ZExt |
|
2013-11-15 09:34:59 +08:00
|
|
|
{ 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 |
|
2015-05-29 08:04:30 +08:00
|
|
|
{ 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // FPTrunc |
|
2013-11-15 09:34:59 +08:00
|
|
|
{ 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 -+
|
2006-11-27 09:05:10 +08:00
|
|
|
};
|
2013-11-15 09:34:59 +08:00
|
|
|
|
2015-12-12 08:33:36 +08:00
|
|
|
// TODO: This logic could be encoded into the table above and handled in the
|
|
|
|
// switch below.
|
2010-07-12 09:19:22 +08:00
|
|
|
// If either of the casts are a bitcast from scalar to vector, disallow the
|
2015-12-12 08:33:36 +08:00
|
|
|
// 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;
|
2006-11-27 09:05:10 +08:00
|
|
|
|
|
|
|
int ElimCase = CastResults[firstOp-Instruction::CastOpsBegin]
|
|
|
|
[secondOp-Instruction::CastOpsBegin];
|
|
|
|
switch (ElimCase) {
|
|
|
|
case 0:
|
2013-11-15 09:34:59 +08:00
|
|
|
// Categorically disallowed.
|
2006-11-27 09:05:10 +08:00
|
|
|
return 0;
|
|
|
|
case 1:
|
2013-11-15 09:34:59 +08:00
|
|
|
// Allowed, use first cast's opcode.
|
2006-11-27 09:05:10 +08:00
|
|
|
return firstOp;
|
|
|
|
case 2:
|
2013-11-15 09:34:59 +08:00
|
|
|
// Allowed, use second cast's opcode.
|
2006-11-27 09:05:10 +08:00
|
|
|
return secondOp;
|
|
|
|
case 3:
|
2013-11-15 09:34:59 +08:00
|
|
|
// No-op cast in second op implies firstOp as long as the DestTy
|
2010-01-23 12:35:57 +08:00
|
|
|
// is integer and we are not converting between a vector and a
|
2013-12-05 13:44:44 +08:00
|
|
|
// non-vector type.
|
2010-02-16 19:11:14 +08:00
|
|
|
if (!SrcTy->isVectorTy() && DstTy->isIntegerTy())
|
2006-11-27 09:05:10 +08:00
|
|
|
return firstOp;
|
|
|
|
return 0;
|
|
|
|
case 4:
|
2013-11-15 09:34:59 +08:00
|
|
|
// No-op cast in second op implies firstOp as long as the DestTy
|
2010-01-23 12:42:42 +08:00
|
|
|
// is floating point.
|
2010-02-16 00:12:20 +08:00
|
|
|
if (DstTy->isFloatingPointTy())
|
2006-11-27 09:05:10 +08:00
|
|
|
return firstOp;
|
|
|
|
return 0;
|
|
|
|
case 5:
|
2013-11-15 09:34:59 +08:00
|
|
|
// No-op cast in first op implies secondOp as long as the SrcTy
|
2010-01-23 12:42:42 +08:00
|
|
|
// is an integer.
|
2010-02-16 00:12:20 +08:00
|
|
|
if (SrcTy->isIntegerTy())
|
2006-11-27 09:05:10 +08:00
|
|
|
return secondOp;
|
|
|
|
return 0;
|
|
|
|
case 6:
|
2013-11-15 09:34:59 +08:00
|
|
|
// No-op cast in first op implies secondOp as long as the SrcTy
|
2010-01-23 12:42:42 +08:00
|
|
|
// is a floating point.
|
2010-02-16 00:12:20 +08:00
|
|
|
if (SrcTy->isFloatingPointTy())
|
2006-11-27 09:05:10 +08:00
|
|
|
return secondOp;
|
|
|
|
return 0;
|
2013-07-31 06:27:10 +08:00
|
|
|
case 7: {
|
2013-11-15 09:34:59 +08:00
|
|
|
// Cannot simplify if address spaces are different!
|
|
|
|
if (SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace())
|
|
|
|
return 0;
|
|
|
|
|
2013-07-31 06:27:10 +08:00
|
|
|
unsigned MidSize = MidTy->getScalarSizeInBits();
|
2013-11-15 09:34:59 +08:00
|
|
|
// 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)
|
2013-07-31 06:27:10 +08:00
|
|
|
return Instruction::BitCast;
|
|
|
|
|
|
|
|
// ptrtoint, inttoptr -> bitcast (ptr -> ptr) if int size is >= ptr size.
|
2012-10-31 00:03:32 +08:00
|
|
|
if (!SrcIntPtrTy || DstIntPtrTy != SrcIntPtrTy)
|
2009-07-22 07:19:40 +08:00
|
|
|
return 0;
|
2012-10-31 00:03:32 +08:00
|
|
|
unsigned PtrSize = SrcIntPtrTy->getScalarSizeInBits();
|
2006-11-27 09:05:10 +08:00
|
|
|
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)
|
2009-06-16 06:12:54 +08:00
|
|
|
unsigned SrcSize = SrcTy->getScalarSizeInBits();
|
|
|
|
unsigned DstSize = DstTy->getScalarSizeInBits();
|
2006-11-27 09:05:10 +08:00
|
|
|
if (SrcSize == DstSize)
|
|
|
|
return Instruction::BitCast;
|
|
|
|
else if (SrcSize < DstSize)
|
|
|
|
return firstOp;
|
|
|
|
return secondOp;
|
|
|
|
}
|
2013-11-15 09:34:59 +08:00
|
|
|
case 9:
|
|
|
|
// zext, sext -> zext, because sext can't sign extend after zext
|
2006-11-27 09:05:10 +08:00
|
|
|
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.
|
2013-07-31 06:27:10 +08:00
|
|
|
case 11: {
|
2006-11-27 09:05:10 +08:00
|
|
|
// inttoptr, ptrtoint -> bitcast if SrcSize<=PtrSize and SrcSize==DstSize
|
2012-10-31 00:03:32 +08:00
|
|
|
if (!MidIntPtrTy)
|
2009-07-22 07:19:40 +08:00
|
|
|
return 0;
|
2012-10-31 00:03:32 +08:00
|
|
|
unsigned PtrSize = MidIntPtrTy->getScalarSizeInBits();
|
2009-06-16 06:12:54 +08:00
|
|
|
unsigned SrcSize = SrcTy->getScalarSizeInBits();
|
|
|
|
unsigned DstSize = DstTy->getScalarSizeInBits();
|
2006-11-27 09:05:10 +08:00
|
|
|
if (SrcSize <= PtrSize && SrcSize == DstSize)
|
|
|
|
return Instruction::BitCast;
|
|
|
|
return 0;
|
|
|
|
}
|
2017-05-16 05:57:41 +08:00
|
|
|
case 12:
|
2013-11-15 09:34:59 +08:00
|
|
|
// 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:
|
2014-06-07 05:52:55 +08:00
|
|
|
// bitcast, addrspacecast -> addrspacecast if the element type of
|
|
|
|
// bitcast's source is the same as that of addrspacecast's destination.
|
2016-11-13 14:58:45 +08:00
|
|
|
if (SrcTy->getScalarType()->getPointerElementType() ==
|
|
|
|
DstTy->getScalarType()->getPointerElementType())
|
2014-06-07 05:52:55 +08:00
|
|
|
return Instruction::AddrSpaceCast;
|
|
|
|
return 0;
|
2013-11-15 09:34:59 +08:00
|
|
|
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;
|
2015-04-21 08:05:41 +08:00
|
|
|
case 17:
|
|
|
|
// (sitofp (zext x)) -> (uitofp x)
|
|
|
|
return Instruction::UIToFP;
|
2006-11-27 09:05:10 +08:00
|
|
|
case 99:
|
2013-11-15 09:34:59 +08:00
|
|
|
// Cast combination can't happen (error in input). This is for all cases
|
2006-11-27 09:05:10 +08:00
|
|
|
// where the MidTy is not the same for the two cast instructions.
|
2012-02-06 06:14:15 +08:00
|
|
|
llvm_unreachable("Invalid Cast Combination");
|
2006-11-27 09:05:10 +08:00
|
|
|
default:
|
2012-02-06 06:14:15 +08:00
|
|
|
llvm_unreachable("Error in CastResults table!!!");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name, Instruction *InsertBefore) {
|
2011-05-18 17:21:57 +08:00
|
|
|
assert(castIsValid(op, S, Ty) && "Invalid cast!");
|
2006-11-27 09:05:10 +08:00
|
|
|
// Construct and return the appropriate CastInst subclass
|
|
|
|
switch (op) {
|
2013-11-15 09:34:59 +08:00
|
|
|
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");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name, BasicBlock *InsertAtEnd) {
|
2011-05-18 17:21:57 +08:00
|
|
|
assert(castIsValid(op, S, Ty) && "Invalid cast!");
|
2006-11-27 09:05:10 +08:00
|
|
|
// Construct and return the appropriate CastInst subclass
|
|
|
|
switch (op) {
|
2013-11-15 09:34:59 +08:00
|
|
|
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");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::CreateZExtOrBitCast(Value *S, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-12-05 04:17:56 +08:00
|
|
|
Instruction *InsertBefore) {
|
2009-06-16 06:12:54 +08:00
|
|
|
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
|
|
|
|
return Create(Instruction::ZExt, S, Ty, Name, InsertBefore);
|
2006-12-05 04:17:56 +08:00
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::CreateZExtOrBitCast(Value *S, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-12-05 04:17:56 +08:00
|
|
|
BasicBlock *InsertAtEnd) {
|
2009-06-16 06:12:54 +08:00
|
|
|
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
|
|
|
|
return Create(Instruction::ZExt, S, Ty, Name, InsertAtEnd);
|
2006-12-05 04:17:56 +08:00
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::CreateSExtOrBitCast(Value *S, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-12-05 04:17:56 +08:00
|
|
|
Instruction *InsertBefore) {
|
2009-06-16 06:12:54 +08:00
|
|
|
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
|
|
|
|
return Create(Instruction::SExt, S, Ty, Name, InsertBefore);
|
2006-12-05 04:17:56 +08:00
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::CreateSExtOrBitCast(Value *S, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-12-05 04:17:56 +08:00
|
|
|
BasicBlock *InsertAtEnd) {
|
2009-06-16 06:12:54 +08:00
|
|
|
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
|
|
|
|
return Create(Instruction::SExt, S, Ty, Name, InsertAtEnd);
|
2006-12-05 04:17:56 +08:00
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::CreateTruncOrBitCast(Value *S, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-12-05 04:17:56 +08:00
|
|
|
Instruction *InsertBefore) {
|
2009-06-16 06:12:54 +08:00
|
|
|
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
|
|
|
|
return Create(Instruction::Trunc, S, Ty, Name, InsertBefore);
|
2006-12-05 04:17:56 +08:00
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::CreateTruncOrBitCast(Value *S, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-12-05 04:17:56 +08:00
|
|
|
BasicBlock *InsertAtEnd) {
|
2009-06-16 06:12:54 +08:00
|
|
|
if (S->getType()->getScalarSizeInBits() == Ty->getScalarSizeInBits())
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
|
|
|
|
return Create(Instruction::Trunc, S, Ty, Name, InsertAtEnd);
|
2006-12-05 04:17:56 +08:00
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-12-05 11:28:26 +08:00
|
|
|
BasicBlock *InsertAtEnd) {
|
2013-07-31 08:17:33 +08:00
|
|
|
assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast");
|
|
|
|
assert((Ty->isIntOrIntVectorTy() || Ty->isPtrOrPtrVectorTy()) &&
|
|
|
|
"Invalid cast");
|
|
|
|
assert(Ty->isVectorTy() == S->getType()->isVectorTy() && "Invalid cast");
|
2013-07-31 12:07:28 +08:00
|
|
|
assert((!Ty->isVectorTy() ||
|
|
|
|
Ty->getVectorNumElements() == S->getType()->getVectorNumElements()) &&
|
2006-12-05 11:28:26 +08:00
|
|
|
"Invalid cast");
|
|
|
|
|
2013-07-31 08:17:33 +08:00
|
|
|
if (Ty->isIntOrIntVectorTy())
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(Instruction::PtrToInt, S, Ty, Name, InsertAtEnd);
|
2013-11-15 09:34:59 +08:00
|
|
|
|
2014-07-15 01:24:35 +08:00
|
|
|
return CreatePointerBitCastOrAddrSpaceCast(S, Ty, Name, InsertAtEnd);
|
2006-12-05 11:28:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// @brief Create a BitCast or a PtrToInt cast instruction
|
2013-07-31 08:17:33 +08:00
|
|
|
CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty,
|
|
|
|
const Twine &Name,
|
2006-12-05 11:28:26 +08:00
|
|
|
Instruction *InsertBefore) {
|
2013-01-16 00:43:00 +08:00
|
|
|
assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast");
|
|
|
|
assert((Ty->isIntOrIntVectorTy() || Ty->isPtrOrPtrVectorTy()) &&
|
2006-12-05 11:28:26 +08:00
|
|
|
"Invalid cast");
|
2013-07-31 08:17:33 +08:00
|
|
|
assert(Ty->isVectorTy() == S->getType()->isVectorTy() && "Invalid cast");
|
2013-07-31 12:07:28 +08:00
|
|
|
assert((!Ty->isVectorTy() ||
|
|
|
|
Ty->getVectorNumElements() == S->getType()->getVectorNumElements()) &&
|
2013-07-31 08:17:33 +08:00
|
|
|
"Invalid cast");
|
2006-12-05 11:28:26 +08:00
|
|
|
|
2013-01-16 00:43:00 +08:00
|
|
|
if (Ty->isIntOrIntVectorTy())
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(Instruction::PtrToInt, S, Ty, Name, InsertBefore);
|
2013-11-15 09:34:59 +08:00
|
|
|
|
2014-07-15 01:24:35 +08:00
|
|
|
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())
|
2013-11-15 09:34:59 +08:00
|
|
|
return Create(Instruction::AddrSpaceCast, S, Ty, Name, InsertBefore);
|
|
|
|
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
|
2006-12-05 11:28:26 +08:00
|
|
|
}
|
|
|
|
|
2014-11-25 16:20:27 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-07-15 01:24:35 +08:00
|
|
|
CastInst *CastInst::CreateIntegerCast(Value *C, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
bool isSigned, const Twine &Name,
|
2006-12-12 08:49:44 +08:00
|
|
|
Instruction *InsertBefore) {
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(C->getType()->isIntOrIntVectorTy() && Ty->isIntOrIntVectorTy() &&
|
2010-01-11 04:21:42 +08:00
|
|
|
"Invalid integer cast");
|
2009-06-16 06:12:54 +08:00
|
|
|
unsigned SrcBits = C->getType()->getScalarSizeInBits();
|
|
|
|
unsigned DstBits = Ty->getScalarSizeInBits();
|
2006-12-12 08:49:44 +08:00
|
|
|
Instruction::CastOps opcode =
|
|
|
|
(SrcBits == DstBits ? Instruction::BitCast :
|
|
|
|
(SrcBits > DstBits ? Instruction::Trunc :
|
|
|
|
(isSigned ? Instruction::SExt : Instruction::ZExt)));
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(opcode, C, Ty, Name, InsertBefore);
|
2006-12-12 08:49:44 +08:00
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::CreateIntegerCast(Value *C, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
bool isSigned, const Twine &Name,
|
2006-12-12 08:49:44 +08:00
|
|
|
BasicBlock *InsertAtEnd) {
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(C->getType()->isIntOrIntVectorTy() && Ty->isIntOrIntVectorTy() &&
|
2009-06-16 06:25:12 +08:00
|
|
|
"Invalid cast");
|
2009-06-16 06:12:54 +08:00
|
|
|
unsigned SrcBits = C->getType()->getScalarSizeInBits();
|
|
|
|
unsigned DstBits = Ty->getScalarSizeInBits();
|
2006-12-12 08:49:44 +08:00
|
|
|
Instruction::CastOps opcode =
|
|
|
|
(SrcBits == DstBits ? Instruction::BitCast :
|
|
|
|
(SrcBits > DstBits ? Instruction::Trunc :
|
|
|
|
(isSigned ? Instruction::SExt : Instruction::ZExt)));
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(opcode, C, Ty, Name, InsertAtEnd);
|
2006-12-12 08:49:44 +08:00
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::CreateFPCast(Value *C, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-12-12 08:49:44 +08:00
|
|
|
Instruction *InsertBefore) {
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() &&
|
2006-12-12 08:49:44 +08:00
|
|
|
"Invalid cast");
|
2009-06-16 06:12:54 +08:00
|
|
|
unsigned SrcBits = C->getType()->getScalarSizeInBits();
|
|
|
|
unsigned DstBits = Ty->getScalarSizeInBits();
|
2006-12-12 08:49:44 +08:00
|
|
|
Instruction::CastOps opcode =
|
|
|
|
(SrcBits == DstBits ? Instruction::BitCast :
|
|
|
|
(SrcBits > DstBits ? Instruction::FPTrunc : Instruction::FPExt));
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(opcode, C, Ty, Name, InsertBefore);
|
2006-12-12 08:49:44 +08:00
|
|
|
}
|
|
|
|
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst *CastInst::CreateFPCast(Value *C, Type *Ty,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name,
|
2006-12-12 08:49:44 +08:00
|
|
|
BasicBlock *InsertAtEnd) {
|
2010-02-16 00:12:20 +08:00
|
|
|
assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() &&
|
2006-12-12 08:49:44 +08:00
|
|
|
"Invalid cast");
|
2009-06-16 06:12:54 +08:00
|
|
|
unsigned SrcBits = C->getType()->getScalarSizeInBits();
|
|
|
|
unsigned DstBits = Ty->getScalarSizeInBits();
|
2006-12-12 08:49:44 +08:00
|
|
|
Instruction::CastOps opcode =
|
|
|
|
(SrcBits == DstBits ? Instruction::BitCast :
|
|
|
|
(SrcBits > DstBits ? Instruction::FPTrunc : Instruction::FPExt));
|
2008-05-17 03:29:10 +08:00
|
|
|
return Create(opcode, C, Ty, Name, InsertAtEnd);
|
2006-12-12 08:49:44 +08:00
|
|
|
}
|
|
|
|
|
2013-07-31 06:02:14 +08:00
|
|
|
// 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
|
2015-03-24 03:51:23 +08:00
|
|
|
if (SrcTy->isIntegerTy()) // Casting from integral
|
2013-07-31 06:02:14 +08:00
|
|
|
return true;
|
2015-03-24 03:51:23 +08:00
|
|
|
if (SrcTy->isFloatingPointTy()) // Casting from floating pt
|
2013-07-31 06:02:14 +08:00
|
|
|
return true;
|
2015-03-24 03:51:23 +08:00
|
|
|
if (SrcTy->isVectorTy()) // Casting from vector
|
2013-07-31 06:02:14 +08:00
|
|
|
return DestBits == SrcBits;
|
2015-03-24 03:51:23 +08:00
|
|
|
// Casting from something else
|
|
|
|
return SrcTy->isPointerTy();
|
|
|
|
}
|
|
|
|
if (DestTy->isFloatingPointTy()) { // Casting to floating pt
|
|
|
|
if (SrcTy->isIntegerTy()) // Casting from integral
|
2013-07-31 06:02:14 +08:00
|
|
|
return true;
|
2015-03-24 03:51:23 +08:00
|
|
|
if (SrcTy->isFloatingPointTy()) // Casting from floating pt
|
2013-07-31 06:02:14 +08:00
|
|
|
return true;
|
2015-03-24 03:51:23 +08:00
|
|
|
if (SrcTy->isVectorTy()) // Casting from vector
|
2013-07-31 06:02:14 +08:00
|
|
|
return DestBits == SrcBits;
|
2015-03-24 03:51:23 +08:00
|
|
|
// Casting from something else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (DestTy->isVectorTy()) // Casting to vector
|
2013-07-31 06:02:14 +08:00
|
|
|
return DestBits == SrcBits;
|
2015-03-24 03:51:23 +08:00
|
|
|
if (DestTy->isPointerTy()) { // Casting to pointer
|
|
|
|
if (SrcTy->isPointerTy()) // Casting from pointer
|
2013-07-31 06:02:14 +08:00
|
|
|
return true;
|
2015-03-24 03:51:23 +08:00
|
|
|
return SrcTy->isIntegerTy(); // Casting from integral
|
|
|
|
}
|
|
|
|
if (DestTy->isX86_MMXTy()) {
|
|
|
|
if (SrcTy->isVectorTy())
|
2013-07-31 06:02:14 +08:00
|
|
|
return DestBits == SrcBits; // 64-bit vector to MMX
|
|
|
|
return false;
|
2015-03-24 03:51:23 +08:00
|
|
|
} // Casting to something else
|
|
|
|
return false;
|
2013-07-31 06:02:14 +08:00
|
|
|
}
|
|
|
|
|
2013-07-31 04:45:05 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-11-25 16:20:27 +08:00
|
|
|
bool CastInst::isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy,
|
2015-03-10 10:37:25 +08:00
|
|
|
const DataLayout &DL) {
|
2017-10-23 04:28:17 +08:00
|
|
|
// ptrtoint and inttoptr are not allowed on non-integral pointers
|
2014-11-25 16:20:27 +08:00
|
|
|
if (auto *PtrTy = dyn_cast<PointerType>(SrcTy))
|
|
|
|
if (auto *IntTy = dyn_cast<IntegerType>(DestTy))
|
2017-10-23 04:28:17 +08:00
|
|
|
return (IntTy->getBitWidth() == DL.getPointerTypeSizeInBits(PtrTy) &&
|
|
|
|
!DL.isNonIntegralPointerType(PtrTy));
|
2014-11-25 16:20:27 +08:00
|
|
|
if (auto *PtrTy = dyn_cast<PointerType>(DestTy))
|
|
|
|
if (auto *IntTy = dyn_cast<IntegerType>(SrcTy))
|
2017-10-23 04:28:17 +08:00
|
|
|
return (IntTy->getBitWidth() == DL.getPointerTypeSizeInBits(PtrTy) &&
|
|
|
|
!DL.isNonIntegralPointerType(PtrTy));
|
2014-11-25 16:20:27 +08:00
|
|
|
|
|
|
|
return isBitCastable(SrcTy, DestTy);
|
|
|
|
}
|
|
|
|
|
2013-07-31 04:45:05 +08:00
|
|
|
// 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
|
2007-01-17 10:46:11 +08:00
|
|
|
// 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"
|
2006-11-27 09:05:10 +08:00
|
|
|
// casting opcode for the arguments passed to it.
|
2008-01-06 18:12:28 +08:00
|
|
|
// This routine must be kept in sync with isCastable.
|
2006-11-27 09:05:10 +08:00
|
|
|
Instruction::CastOps
|
2006-12-04 10:43:42 +08:00
|
|
|
CastInst::getCastOpcode(
|
2011-07-18 12:54:35 +08:00
|
|
|
const Value *Src, bool SrcIsSigned, Type *DestTy, bool DestIsSigned) {
|
|
|
|
Type *SrcTy = Src->getType();
|
2006-11-27 09:05:10 +08:00
|
|
|
|
2008-01-06 18:12:28 +08:00
|
|
|
assert(SrcTy->isFirstClassType() && DestTy->isFirstClassType() &&
|
|
|
|
"Only first class types are castable!");
|
|
|
|
|
2011-05-18 15:13:41 +08:00
|
|
|
if (SrcTy == DestTy)
|
|
|
|
return BitCast;
|
|
|
|
|
2013-07-31 04:45:05 +08:00
|
|
|
// FIXME: Check address space sizes here
|
2011-07-18 12:54:35 +08:00
|
|
|
if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy))
|
|
|
|
if (VectorType *DestVecTy = dyn_cast<VectorType>(DestTy))
|
2011-05-18 15:13:41 +08:00
|
|
|
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
|
2011-05-18 17:21:57 +08:00
|
|
|
unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr
|
|
|
|
unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr
|
2011-05-18 15:13:41 +08:00
|
|
|
|
2006-11-27 09:05:10 +08:00
|
|
|
// Run through the possibilities ...
|
2010-02-16 00:12:20 +08:00
|
|
|
if (DestTy->isIntegerTy()) { // Casting to integral
|
|
|
|
if (SrcTy->isIntegerTy()) { // Casting from integral
|
2006-11-27 09:05:10 +08:00
|
|
|
if (DestBits < SrcBits)
|
|
|
|
return Trunc; // int -> smaller int
|
|
|
|
else if (DestBits > SrcBits) { // its an extension
|
2006-12-04 10:43:42 +08:00
|
|
|
if (SrcIsSigned)
|
2006-11-27 09:05:10 +08:00
|
|
|
return SExt; // signed -> SEXT
|
|
|
|
else
|
|
|
|
return ZExt; // unsigned -> ZEXT
|
|
|
|
} else {
|
|
|
|
return BitCast; // Same size, No-op cast
|
|
|
|
}
|
2010-02-16 00:12:20 +08:00
|
|
|
} else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt
|
2006-12-04 10:43:42 +08:00
|
|
|
if (DestIsSigned)
|
2006-11-27 09:05:10 +08:00
|
|
|
return FPToSI; // FP -> sint
|
|
|
|
else
|
|
|
|
return FPToUI; // FP -> uint
|
2011-05-18 18:59:25 +08:00
|
|
|
} else if (SrcTy->isVectorTy()) {
|
|
|
|
assert(DestBits == SrcBits &&
|
|
|
|
"Casting vector to integer of different width");
|
2006-11-27 09:05:10 +08:00
|
|
|
return BitCast; // Same size, no-op cast
|
|
|
|
} else {
|
2010-02-16 19:11:14 +08:00
|
|
|
assert(SrcTy->isPointerTy() &&
|
2006-11-27 09:05:10 +08:00
|
|
|
"Casting from a value that is not first-class type");
|
|
|
|
return PtrToInt; // ptr -> int
|
|
|
|
}
|
2010-02-16 00:12:20 +08:00
|
|
|
} else if (DestTy->isFloatingPointTy()) { // Casting to floating pt
|
|
|
|
if (SrcTy->isIntegerTy()) { // Casting from integral
|
2006-12-04 10:43:42 +08:00
|
|
|
if (SrcIsSigned)
|
2006-11-27 09:05:10 +08:00
|
|
|
return SIToFP; // sint -> FP
|
|
|
|
else
|
|
|
|
return UIToFP; // uint -> FP
|
2010-02-16 00:12:20 +08:00
|
|
|
} else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt
|
2006-11-27 09:05:10 +08:00
|
|
|
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
|
|
|
|
}
|
2011-05-18 18:59:25 +08:00
|
|
|
} else if (SrcTy->isVectorTy()) {
|
|
|
|
assert(DestBits == SrcBits &&
|
2007-05-12 05:43:24 +08:00
|
|
|
"Casting vector to floating point of different width");
|
2008-11-05 09:37:40 +08:00
|
|
|
return BitCast; // same size, no-op cast
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
2012-02-19 19:37:01 +08:00
|
|
|
llvm_unreachable("Casting pointer or non-first class to float");
|
2011-05-18 18:59:25 +08:00
|
|
|
} else if (DestTy->isVectorTy()) {
|
|
|
|
assert(DestBits == SrcBits &&
|
|
|
|
"Illegal cast to vector (wrong type or size)");
|
|
|
|
return BitCast;
|
2010-02-16 19:11:14 +08:00
|
|
|
} else if (DestTy->isPointerTy()) {
|
|
|
|
if (SrcTy->isPointerTy()) {
|
2013-11-15 09:34:59 +08:00
|
|
|
if (DestTy->getPointerAddressSpace() != SrcTy->getPointerAddressSpace())
|
|
|
|
return AddrSpaceCast;
|
2006-11-27 09:05:10 +08:00
|
|
|
return BitCast; // ptr -> ptr
|
2010-02-16 00:12:20 +08:00
|
|
|
} else if (SrcTy->isIntegerTy()) {
|
2006-11-27 09:05:10 +08:00
|
|
|
return IntToPtr; // int -> ptr
|
|
|
|
}
|
2012-02-19 19:37:01 +08:00
|
|
|
llvm_unreachable("Casting pointer to other than pointer or int");
|
2010-10-01 07:57:10 +08:00
|
|
|
} else if (DestTy->isX86_MMXTy()) {
|
2011-05-18 18:59:25 +08:00
|
|
|
if (SrcTy->isVectorTy()) {
|
|
|
|
assert(DestBits == SrcBits && "Casting vector of wrong width to X86_MMX");
|
2010-10-01 07:57:10 +08:00
|
|
|
return BitCast; // 64-bit vector to MMX
|
|
|
|
}
|
2012-02-19 19:37:01 +08:00
|
|
|
llvm_unreachable("Illegal cast to X86_MMX");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
2012-02-19 19:37:01 +08:00
|
|
|
llvm_unreachable("Casting to type that is not first-class");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// 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.
|
2007-01-17 10:46:11 +08:00
|
|
|
bool
|
2011-07-18 12:54:35 +08:00
|
|
|
CastInst::castIsValid(Instruction::CastOps op, Value *S, Type *DstTy) {
|
2006-11-27 09:05:10 +08:00
|
|
|
// Check for type sanity on the arguments
|
2011-07-18 12:54:35 +08:00
|
|
|
Type *SrcTy = S->getType();
|
2013-01-11 07:22:53 +08:00
|
|
|
|
2010-01-27 05:51:43 +08:00
|
|
|
if (!SrcTy->isFirstClassType() || !DstTy->isFirstClassType() ||
|
|
|
|
SrcTy->isAggregateType() || DstTy->isAggregateType())
|
2006-11-27 09:05:10 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Get the size of the types in bits, we'll need this later
|
2009-06-16 06:12:54 +08:00
|
|
|
unsigned SrcBitSize = SrcTy->getScalarSizeInBits();
|
|
|
|
unsigned DstBitSize = DstTy->getScalarSizeInBits();
|
2006-11-27 09:05:10 +08:00
|
|
|
|
2011-05-18 17:21:57 +08:00
|
|
|
// 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;
|
|
|
|
|
2006-11-27 09:05:10 +08:00
|
|
|
// Switch on the opcode provided
|
|
|
|
switch (op) {
|
|
|
|
default: return false; // This is an input error
|
|
|
|
case Instruction::Trunc:
|
2011-05-18 17:21:57 +08:00
|
|
|
return SrcTy->isIntOrIntVectorTy() && DstTy->isIntOrIntVectorTy() &&
|
|
|
|
SrcLength == DstLength && SrcBitSize > DstBitSize;
|
2006-11-27 09:05:10 +08:00
|
|
|
case Instruction::ZExt:
|
2011-05-18 17:21:57 +08:00
|
|
|
return SrcTy->isIntOrIntVectorTy() && DstTy->isIntOrIntVectorTy() &&
|
|
|
|
SrcLength == DstLength && SrcBitSize < DstBitSize;
|
2006-11-27 09:05:10 +08:00
|
|
|
case Instruction::SExt:
|
2011-05-18 17:21:57 +08:00
|
|
|
return SrcTy->isIntOrIntVectorTy() && DstTy->isIntOrIntVectorTy() &&
|
|
|
|
SrcLength == DstLength && SrcBitSize < DstBitSize;
|
2006-11-27 09:05:10 +08:00
|
|
|
case Instruction::FPTrunc:
|
2011-05-18 17:21:57 +08:00
|
|
|
return SrcTy->isFPOrFPVectorTy() && DstTy->isFPOrFPVectorTy() &&
|
|
|
|
SrcLength == DstLength && SrcBitSize > DstBitSize;
|
2006-11-27 09:05:10 +08:00
|
|
|
case Instruction::FPExt:
|
2011-05-18 17:21:57 +08:00
|
|
|
return SrcTy->isFPOrFPVectorTy() && DstTy->isFPOrFPVectorTy() &&
|
|
|
|
SrcLength == DstLength && SrcBitSize < DstBitSize;
|
2006-11-27 09:05:10 +08:00
|
|
|
case Instruction::UIToFP:
|
|
|
|
case Instruction::SIToFP:
|
2011-05-18 17:21:57 +08:00
|
|
|
return SrcTy->isIntOrIntVectorTy() && DstTy->isFPOrFPVectorTy() &&
|
|
|
|
SrcLength == DstLength;
|
2006-11-27 09:05:10 +08:00
|
|
|
case Instruction::FPToUI:
|
|
|
|
case Instruction::FPToSI:
|
2011-05-18 17:21:57 +08:00
|
|
|
return SrcTy->isFPOrFPVectorTy() && DstTy->isIntOrIntVectorTy() &&
|
|
|
|
SrcLength == DstLength;
|
2006-11-27 09:05:10 +08:00
|
|
|
case Instruction::PtrToInt:
|
2012-01-25 09:32:59 +08:00
|
|
|
if (isa<VectorType>(SrcTy) != isa<VectorType>(DstTy))
|
2011-12-05 14:29:09 +08:00
|
|
|
return false;
|
2012-01-25 09:32:59 +08:00
|
|
|
if (VectorType *VT = dyn_cast<VectorType>(SrcTy))
|
|
|
|
if (VT->getNumElements() != cast<VectorType>(DstTy)->getNumElements())
|
|
|
|
return false;
|
2017-07-09 15:04:00 +08:00
|
|
|
return SrcTy->isPtrOrPtrVectorTy() && DstTy->isIntOrIntVectorTy();
|
2006-11-27 09:05:10 +08:00
|
|
|
case Instruction::IntToPtr:
|
2012-01-25 09:32:59 +08:00
|
|
|
if (isa<VectorType>(SrcTy) != isa<VectorType>(DstTy))
|
2011-12-05 14:29:09 +08:00
|
|
|
return false;
|
2012-01-25 09:32:59 +08:00
|
|
|
if (VectorType *VT = dyn_cast<VectorType>(SrcTy))
|
|
|
|
if (VT->getNumElements() != cast<VectorType>(DstTy)->getNumElements())
|
|
|
|
return false;
|
2017-07-09 15:04:00 +08:00
|
|
|
return SrcTy->isIntOrIntVectorTy() && DstTy->isPtrOrPtrVectorTy();
|
2014-01-23 03:21:33 +08:00
|
|
|
case Instruction::BitCast: {
|
|
|
|
PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy->getScalarType());
|
|
|
|
PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy->getScalarType());
|
|
|
|
|
2006-11-27 09:05:10 +08:00
|
|
|
// BitCast implies a no-op cast of type only. No bits change.
|
|
|
|
// However, you can't cast pointers to anything but pointers.
|
2014-01-23 03:21:33 +08:00
|
|
|
if (!SrcPtrTy != !DstPtrTy)
|
2006-11-27 09:05:10 +08:00
|
|
|
return false;
|
|
|
|
|
2013-12-05 13:44:44 +08:00
|
|
|
// For non-pointer cases, the cast is okay if the source and destination bit
|
2013-11-15 09:34:59 +08:00
|
|
|
// widths are identical.
|
2014-01-23 03:21:33 +08:00
|
|
|
if (!SrcPtrTy)
|
2013-11-15 09:34:59 +08:00
|
|
|
return SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits();
|
|
|
|
|
2014-01-23 03:21:33 +08:00
|
|
|
// 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;
|
|
|
|
}
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TruncInst::TruncInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, Trunc, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal Trunc");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TruncInst::TruncInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, Trunc, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal Trunc");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ZExtInst::ZExtInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, ZExt, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal ZExt");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ZExtInst::ZExtInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, ZExt, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal ZExt");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
SExtInst::SExtInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, SExt, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SExt");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
2006-12-02 10:22:01 +08:00
|
|
|
SExtInst::SExtInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, SExt, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SExt");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FPTruncInst::FPTruncInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, FPTrunc, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPTrunc");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FPTruncInst::FPTruncInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, FPTrunc, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPTrunc");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FPExtInst::FPExtInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, FPExt, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPExt");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FPExtInst::FPExtInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, FPExt, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPExt");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
UIToFPInst::UIToFPInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, UIToFP, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal UIToFP");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
UIToFPInst::UIToFPInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, UIToFP, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal UIToFP");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SIToFPInst::SIToFPInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, SIToFP, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SIToFP");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SIToFPInst::SIToFPInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, SIToFP, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal SIToFP");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FPToUIInst::FPToUIInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, FPToUI, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToUI");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FPToUIInst::FPToUIInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, FPToUI, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToUI");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FPToSIInst::FPToSIInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, FPToSI, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToSI");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
FPToSIInst::FPToSIInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, FPToSI, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal FPToSI");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PtrToIntInst::PtrToIntInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, PtrToInt, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal PtrToInt");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PtrToIntInst::PtrToIntInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, PtrToInt, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal PtrToInt");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
IntToPtrInst::IntToPtrInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, IntToPtr, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal IntToPtr");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
IntToPtrInst::IntToPtrInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, IntToPtr, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal IntToPtr");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BitCastInst::BitCastInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, BitCast, S, Name, InsertBefore) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal BitCast");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BitCastInst::BitCastInst(
|
2011-07-18 12:54:35 +08:00
|
|
|
Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
|
2006-11-27 09:05:10 +08:00
|
|
|
) : CastInst(Ty, BitCast, S, Name, InsertAtEnd) {
|
2007-01-17 10:46:11 +08:00
|
|
|
assert(castIsValid(getOpcode(), S, Ty) && "Illegal BitCast");
|
2006-11-27 09:05:10 +08:00
|
|
|
}
|
2004-07-29 20:33:25 +08:00
|
|
|
|
2013-11-15 09:34:59 +08:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2006-11-20 09:22:35 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CmpInst Classes
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2015-12-15 14:11:33 +08:00
|
|
|
CmpInst::CmpInst(Type *ty, OtherOps op, Predicate predicate, Value *LHS,
|
|
|
|
Value *RHS, const Twine &Name, Instruction *InsertBefore)
|
2008-05-13 04:11:05 +08:00
|
|
|
: Instruction(ty, op,
|
2008-05-10 16:32:32 +08:00
|
|
|
OperandTraits<CmpInst>::op_begin(this),
|
|
|
|
OperandTraits<CmpInst>::operands(this),
|
|
|
|
InsertBefore) {
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = LHS;
|
|
|
|
Op<1>() = RHS;
|
2009-12-29 10:14:09 +08:00
|
|
|
setPredicate((Predicate)predicate);
|
2007-04-11 21:04:48 +08:00
|
|
|
setName(Name);
|
2008-05-13 03:01:56 +08:00
|
|
|
}
|
|
|
|
|
2015-12-15 14:11:33 +08:00
|
|
|
CmpInst::CmpInst(Type *ty, OtherOps op, Predicate predicate, Value *LHS,
|
|
|
|
Value *RHS, const Twine &Name, BasicBlock *InsertAtEnd)
|
2008-05-13 04:11:05 +08:00
|
|
|
: Instruction(ty, op,
|
2008-05-10 16:32:32 +08:00
|
|
|
OperandTraits<CmpInst>::op_begin(this),
|
|
|
|
OperandTraits<CmpInst>::operands(this),
|
|
|
|
InsertAtEnd) {
|
2008-05-27 05:33:52 +08:00
|
|
|
Op<0>() = LHS;
|
|
|
|
Op<1>() = RHS;
|
2009-12-29 10:14:09 +08:00
|
|
|
setPredicate((Predicate)predicate);
|
2007-04-11 21:04:48 +08:00
|
|
|
setName(Name);
|
2006-11-20 09:22:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CmpInst *
|
2015-12-15 14:11:33 +08:00
|
|
|
CmpInst::Create(OtherOps Op, Predicate predicate, Value *S1, Value *S2,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name, Instruction *InsertBefore) {
|
2006-11-20 09:22:35 +08:00
|
|
|
if (Op == Instruction::ICmp) {
|
2009-07-10 07:48:35 +08:00
|
|
|
if (InsertBefore)
|
|
|
|
return new ICmpInst(InsertBefore, CmpInst::Predicate(predicate),
|
|
|
|
S1, S2, Name);
|
|
|
|
else
|
2009-08-26 07:17:54 +08:00
|
|
|
return new ICmpInst(CmpInst::Predicate(predicate),
|
2009-07-10 07:48:35 +08:00
|
|
|
S1, S2, Name);
|
2008-05-13 03:01:56 +08:00
|
|
|
}
|
2009-07-10 07:48:35 +08:00
|
|
|
|
|
|
|
if (InsertBefore)
|
|
|
|
return new FCmpInst(InsertBefore, CmpInst::Predicate(predicate),
|
|
|
|
S1, S2, Name);
|
|
|
|
else
|
2009-08-26 07:17:54 +08:00
|
|
|
return new FCmpInst(CmpInst::Predicate(predicate),
|
2009-07-10 07:48:35 +08:00
|
|
|
S1, S2, Name);
|
2006-11-20 09:22:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CmpInst *
|
2015-12-15 14:11:33 +08:00
|
|
|
CmpInst::Create(OtherOps Op, Predicate predicate, Value *S1, Value *S2,
|
2009-07-25 12:41:11 +08:00
|
|
|
const Twine &Name, BasicBlock *InsertAtEnd) {
|
2006-11-20 09:22:35 +08:00
|
|
|
if (Op == Instruction::ICmp) {
|
2009-07-10 07:48:35 +08:00
|
|
|
return new ICmpInst(*InsertAtEnd, CmpInst::Predicate(predicate),
|
|
|
|
S1, S2, Name);
|
2008-05-13 03:01:56 +08:00
|
|
|
}
|
2009-07-10 07:48:35 +08:00
|
|
|
return new FCmpInst(*InsertAtEnd, CmpInst::Predicate(predicate),
|
|
|
|
S1, S2, Name);
|
2006-11-20 09:22:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CmpInst::swapOperands() {
|
|
|
|
if (ICmpInst *IC = dyn_cast<ICmpInst>(this))
|
|
|
|
IC->swapOperands();
|
|
|
|
else
|
|
|
|
cast<FCmpInst>(this)->swapOperands();
|
|
|
|
}
|
|
|
|
|
2011-01-04 20:52:29 +08:00
|
|
|
bool CmpInst::isCommutative() const {
|
|
|
|
if (const ICmpInst *IC = dyn_cast<ICmpInst>(this))
|
2006-11-20 09:22:35 +08:00
|
|
|
return IC->isCommutative();
|
|
|
|
return cast<FCmpInst>(this)->isCommutative();
|
|
|
|
}
|
|
|
|
|
2011-01-04 20:52:29 +08:00
|
|
|
bool CmpInst::isEquality() const {
|
|
|
|
if (const ICmpInst *IC = dyn_cast<ICmpInst>(this))
|
2006-11-20 09:22:35 +08:00
|
|
|
return IC->isEquality();
|
|
|
|
return cast<FCmpInst>(this)->isEquality();
|
|
|
|
}
|
|
|
|
|
2008-05-31 10:47:54 +08:00
|
|
|
CmpInst::Predicate CmpInst::getInversePredicate(Predicate pred) {
|
2006-11-20 09:22:35 +08:00
|
|
|
switch (pred) {
|
2012-02-06 06:14:15 +08:00
|
|
|
default: llvm_unreachable("Unknown cmp predicate!");
|
2006-11-20 09:22:35 +08:00
|
|
|
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;
|
|
|
|
|
2008-05-31 10:47:54 +08:00
|
|
|
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;
|
2006-11-20 09:22:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-18 04:25:25 +08:00
|
|
|
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";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-12-23 14:05:41 +08:00
|
|
|
ICmpInst::Predicate ICmpInst::getSignedPredicate(Predicate pred) {
|
|
|
|
switch (pred) {
|
2012-02-06 06:14:15 +08:00
|
|
|
default: llvm_unreachable("Unknown icmp predicate!");
|
2006-12-23 14:05:41 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-28 11:48:02 +08:00
|
|
|
ICmpInst::Predicate ICmpInst::getUnsignedPredicate(Predicate pred) {
|
|
|
|
switch (pred) {
|
2012-02-06 06:14:15 +08:00
|
|
|
default: llvm_unreachable("Unknown icmp predicate!");
|
2008-01-28 11:48:02 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-31 10:47:54 +08:00
|
|
|
CmpInst::Predicate CmpInst::getSwappedPredicate(Predicate pred) {
|
2006-11-20 09:22:35 +08:00
|
|
|
switch (pred) {
|
2012-02-06 06:14:15 +08:00
|
|
|
default: llvm_unreachable("Unknown cmp predicate!");
|
2008-05-31 10:47:54 +08:00
|
|
|
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;
|
|
|
|
|
2006-11-20 09:22:35 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2015-10-23 03:57:34 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
2006-11-20 09:22:35 +08:00
|
|
|
|
2015-12-15 14:11:33 +08:00
|
|
|
bool CmpInst::isUnsigned(Predicate predicate) {
|
2006-12-23 14:05:41 +08:00
|
|
|
switch (predicate) {
|
|
|
|
default: return false;
|
|
|
|
case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_ULE: case ICmpInst::ICMP_UGT:
|
|
|
|
case ICmpInst::ICMP_UGE: return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-15 14:11:33 +08:00
|
|
|
bool CmpInst::isSigned(Predicate predicate) {
|
2006-12-23 14:05:41 +08:00
|
|
|
switch (predicate) {
|
|
|
|
default: return false;
|
|
|
|
case ICmpInst::ICMP_SLT: case ICmpInst::ICMP_SLE: case ICmpInst::ICMP_SGT:
|
|
|
|
case ICmpInst::ICMP_SGE: return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-15 14:11:33 +08:00
|
|
|
bool CmpInst::isOrdered(Predicate predicate) {
|
2006-12-23 14:05:41 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-15 14:11:33 +08:00
|
|
|
bool CmpInst::isUnordered(Predicate predicate) {
|
2006-12-23 14:05:41 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-15 14:11:33 +08:00
|
|
|
bool CmpInst::isTrueWhenEqual(Predicate predicate) {
|
2009-10-25 11:50:03 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-15 14:11:33 +08:00
|
|
|
bool CmpInst::isFalseWhenEqual(Predicate predicate) {
|
2009-10-25 11:50:03 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-22 00:18:02 +08:00
|
|
|
bool CmpInst::isImpliedTrueByMatchingCmp(Predicate Pred1, Predicate Pred2) {
|
2016-04-21 22:04:54 +08:00
|
|
|
// If the predicates match, then we know the first condition implies the
|
|
|
|
// second is true.
|
|
|
|
if (Pred1 == Pred2)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
switch (Pred1) {
|
|
|
|
default:
|
|
|
|
break;
|
2016-04-23 01:57:34 +08:00
|
|
|
case ICMP_EQ:
|
2016-04-25 21:25:14 +08:00
|
|
|
// A == B implies A >=u B, A <=u B, A >=s B, and A <=s B are true.
|
2016-04-23 01:57:34 +08:00
|
|
|
return Pred2 == ICMP_UGE || Pred2 == ICMP_ULE || Pred2 == ICMP_SGE ||
|
|
|
|
Pred2 == ICMP_SLE;
|
2016-04-23 01:14:12 +08:00
|
|
|
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;
|
2016-04-21 22:04:54 +08:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-04-22 00:18:02 +08:00
|
|
|
bool CmpInst::isImpliedFalseByMatchingCmp(Predicate Pred1, Predicate Pred2) {
|
2016-04-23 01:57:34 +08:00
|
|
|
return isImpliedTrueByMatchingCmp(Pred1, getInversePredicate(Pred2));
|
2016-04-21 22:04:54 +08:00
|
|
|
}
|
2009-10-25 11:50:03 +08:00
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// SwitchInst Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-11-17 13:41:46 +08:00
|
|
|
void SwitchInst::init(Value *Value, BasicBlock *Default, unsigned NumReserved) {
|
|
|
|
assert(Value && Default && NumReserved);
|
|
|
|
ReservedSpace = NumReserved;
|
2015-06-13 01:48:10 +08:00
|
|
|
setNumHungOffUseOperands(2);
|
2015-06-11 06:38:46 +08:00
|
|
|
allocHungoffUses(ReservedSpace);
|
2005-01-29 08:35:16 +08:00
|
|
|
|
2015-05-22 06:48:54 +08:00
|
|
|
Op<0>() = Value;
|
|
|
|
Op<1>() = Default;
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2007-02-24 08:55:48 +08:00
|
|
|
/// 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)
|
2009-08-14 05:58:54 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(Value->getContext()), Instruction::Switch,
|
2014-04-09 14:08:46 +08:00
|
|
|
nullptr, 0, InsertBefore) {
|
2010-11-17 13:41:46 +08:00
|
|
|
init(Value, Default, 2+NumCases*2);
|
2007-02-24 08:55:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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)
|
2009-08-14 05:58:54 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(Value->getContext()), Instruction::Switch,
|
2014-04-09 14:08:46 +08:00
|
|
|
nullptr, 0, InsertAtEnd) {
|
2010-11-17 13:41:46 +08:00
|
|
|
init(Value, Default, 2+NumCases*2);
|
2007-02-24 08:55:48 +08:00
|
|
|
}
|
|
|
|
|
2005-04-22 07:48:37 +08:00
|
|
|
SwitchInst::SwitchInst(const SwitchInst &SI)
|
2014-04-09 14:08:46 +08:00
|
|
|
: TerminatorInst(SI.getType(), Instruction::Switch, nullptr, 0) {
|
2010-11-17 13:41:46 +08:00
|
|
|
init(SI.getCondition(), SI.getDefaultDest(), SI.getNumOperands());
|
2015-06-13 01:48:10 +08:00
|
|
|
setNumHungOffUseOperands(SI.getNumOperands());
|
2015-06-13 01:48:05 +08:00
|
|
|
Use *OL = getOperandList();
|
|
|
|
const Use *InOL = SI.getOperandList();
|
2010-11-17 13:41:46 +08:00
|
|
|
for (unsigned i = 2, E = SI.getNumOperands(); i != E; i += 2) {
|
2008-05-27 05:33:52 +08:00
|
|
|
OL[i] = InOL[i];
|
|
|
|
OL[i+1] = InOL[i+1];
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
2009-08-26 06:11:20 +08:00
|
|
|
SubclassOptionalData = SI.SubclassOptionalData;
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
2005-01-29 08:35:16 +08:00
|
|
|
|
2004-07-29 20:33:25 +08:00
|
|
|
/// addCase - Add an entry to the switch instruction...
|
|
|
|
///
|
2005-02-24 13:32:09 +08:00
|
|
|
void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {
|
2015-06-13 01:48:10 +08:00
|
|
|
unsigned NewCaseIdx = getNumCases();
|
|
|
|
unsigned OpNo = getNumOperands();
|
2005-01-29 08:35:16 +08:00
|
|
|
if (OpNo+2 > ReservedSpace)
|
2011-04-01 16:00:58 +08:00
|
|
|
growOperands(); // Get more space!
|
2005-01-29 08:35:16 +08:00
|
|
|
// Initialize some new operands.
|
2005-01-29 09:05:12 +08:00
|
|
|
assert(OpNo+1 < ReservedSpace && "Growing didn't work!");
|
2015-06-13 01:48:10 +08:00
|
|
|
setNumHungOffUseOperands(OpNo+2);
|
2017-04-12 15:27:28 +08:00
|
|
|
CaseHandle Case(this, NewCaseIdx);
|
Revert patches to add case-range support for PR1255.
The work on this project was left in an unfinished and inconsistent state.
Hopefully someone will eventually get a chance to implement this feature, but
in the meantime, it is better to put things back the way the were. I have
left support in the bitcode reader to handle the case-range bitcode format,
so that we do not lose bitcode compatibility with the llvm 3.3 release.
This reverts the following commits: 155464, 156374, 156377, 156613, 156704,
156757, 156804 156808, 156985, 157046, 157112, 157183, 157315, 157384, 157575,
157576, 157586, 157612, 157810, 157814, 157815, 157880, 157881, 157882, 157884,
157887, 157901, 158979, 157987, 157989, 158986, 158997, 159076, 159101, 159100,
159200, 159201, 159207, 159527, 159532, 159540, 159583, 159618, 159658, 159659,
159660, 159661, 159703, 159704, 160076, 167356, 172025, 186736
llvm-svn: 190328
2013-09-10 03:14:35 +08:00
|
|
|
Case.setValue(OnVal);
|
2012-03-08 15:06:20 +08:00
|
|
|
Case.setSuccessor(Dest);
|
2004-07-29 20:33:25 +08:00
|
|
|
}
|
|
|
|
|
SwitchInst refactoring.
The purpose of refactoring is to hide operand roles from SwitchInst user (programmer). If you want to play with operands directly, probably you will need lower level methods than SwitchInst ones (TerminatorInst or may be User). After this patch we can reorganize SwitchInst operands and successors as we want.
What was done:
1. Changed semantics of index inside the getCaseValue method:
getCaseValue(0) means "get first case", not a condition. Use getCondition() if you want to resolve the condition. I propose don't mix SwitchInst case indexing with low level indexing (TI successors indexing, User's operands indexing), since it may be dangerous.
2. By the same reason findCaseValue(ConstantInt*) returns actual number of case value. 0 means first case, not default. If there is no case with given value, ErrorIndex will returned.
3. Added getCaseSuccessor method. I propose to avoid usage of TerminatorInst::getSuccessor if you want to resolve case successor BB. Use getCaseSuccessor instead, since internal SwitchInst organization of operands/successors is hidden and may be changed in any moment.
4. Added resolveSuccessorIndex and resolveCaseIndex. The main purpose of these methods is to see how case successors are really mapped in TerminatorInst.
4.1 "resolveSuccessorIndex" was created if you need to level down from SwitchInst to TerminatorInst. It returns TerminatorInst's successor index for given case successor.
4.2 "resolveCaseIndex" converts low level successors index to case index that curresponds to the given successor.
Note: There are also related compatability fix patches for dragonegg, klee, llvm-gcc-4.0, llvm-gcc-4.2, safecode, clang.
llvm-svn: 149481
2012-02-01 15:49:51 +08:00
|
|
|
/// removeCase - This method removes the specified case and its successor
|
|
|
|
/// from the switch instruction.
|
2017-04-12 15:27:28 +08:00
|
|
|
SwitchInst::CaseIt SwitchInst::removeCase(CaseIt I) {
|
|
|
|
unsigned idx = I->getCaseIndex();
|
|
|
|
|
SwitchInst refactoring.
The purpose of refactoring is to hide operand roles from SwitchInst user (programmer). If you want to play with operands directly, probably you will need lower level methods than SwitchInst ones (TerminatorInst or may be User). After this patch we can reorganize SwitchInst operands and successors as we want.
What was done:
1. Changed semantics of index inside the getCaseValue method:
getCaseValue(0) means "get first case", not a condition. Use getCondition() if you want to resolve the condition. I propose don't mix SwitchInst case indexing with low level indexing (TI successors indexing, User's operands indexing), since it may be dangerous.
2. By the same reason findCaseValue(ConstantInt*) returns actual number of case value. 0 means first case, not default. If there is no case with given value, ErrorIndex will returned.
3. Added getCaseSuccessor method. I propose to avoid usage of TerminatorInst::getSuccessor if you want to resolve case successor BB. Use getCaseSuccessor instead, since internal SwitchInst organization of operands/successors is hidden and may be changed in any moment.
4. Added resolveSuccessorIndex and resolveCaseIndex. The main purpose of these methods is to see how case successors are really mapped in TerminatorInst.
4.1 "resolveSuccessorIndex" was created if you need to level down from SwitchInst to TerminatorInst. It returns TerminatorInst's successor index for given case successor.
4.2 "resolveCaseIndex" converts low level successors index to case index that curresponds to the given successor.
Note: There are also related compatability fix patches for dragonegg, klee, llvm-gcc-4.0, llvm-gcc-4.2, safecode, clang.
llvm-svn: 149481
2012-02-01 15:49:51 +08:00
|
|
|
assert(2 + idx*2 < getNumOperands() && "Case index out of range!!!");
|
2005-01-29 08:35:16 +08:00
|
|
|
|
|
|
|
unsigned NumOps = getNumOperands();
|
2015-06-13 01:48:05 +08:00
|
|
|
Use *OL = getOperandList();
|
2005-01-29 08:35:16 +08:00
|
|
|
|
2011-02-01 17:22:34 +08:00
|
|
|
// Overwrite this case with the end of the list.
|
SwitchInst refactoring.
The purpose of refactoring is to hide operand roles from SwitchInst user (programmer). If you want to play with operands directly, probably you will need lower level methods than SwitchInst ones (TerminatorInst or may be User). After this patch we can reorganize SwitchInst operands and successors as we want.
What was done:
1. Changed semantics of index inside the getCaseValue method:
getCaseValue(0) means "get first case", not a condition. Use getCondition() if you want to resolve the condition. I propose don't mix SwitchInst case indexing with low level indexing (TI successors indexing, User's operands indexing), since it may be dangerous.
2. By the same reason findCaseValue(ConstantInt*) returns actual number of case value. 0 means first case, not default. If there is no case with given value, ErrorIndex will returned.
3. Added getCaseSuccessor method. I propose to avoid usage of TerminatorInst::getSuccessor if you want to resolve case successor BB. Use getCaseSuccessor instead, since internal SwitchInst organization of operands/successors is hidden and may be changed in any moment.
4. Added resolveSuccessorIndex and resolveCaseIndex. The main purpose of these methods is to see how case successors are really mapped in TerminatorInst.
4.1 "resolveSuccessorIndex" was created if you need to level down from SwitchInst to TerminatorInst. It returns TerminatorInst's successor index for given case successor.
4.2 "resolveCaseIndex" converts low level successors index to case index that curresponds to the given successor.
Note: There are also related compatability fix patches for dragonegg, klee, llvm-gcc-4.0, llvm-gcc-4.2, safecode, clang.
llvm-svn: 149481
2012-02-01 15:49:51 +08:00
|
|
|
if (2 + (idx + 1) * 2 != NumOps) {
|
|
|
|
OL[2 + idx * 2] = OL[NumOps - 2];
|
|
|
|
OL[2 + idx * 2 + 1] = OL[NumOps - 1];
|
2005-01-29 08:35:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Nuke the last value.
|
2014-04-09 14:08:46 +08:00
|
|
|
OL[NumOps-2].set(nullptr);
|
|
|
|
OL[NumOps-2+1].set(nullptr);
|
2015-06-13 01:48:10 +08:00
|
|
|
setNumHungOffUseOperands(NumOps-2);
|
2017-03-26 10:49:23 +08:00
|
|
|
|
|
|
|
return CaseIt(this, idx);
|
2005-01-29 08:35:16 +08:00
|
|
|
}
|
|
|
|
|
2011-04-01 16:00:58 +08:00
|
|
|
/// 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.
|
2005-01-29 08:35:16 +08:00
|
|
|
///
|
2011-04-01 16:00:58 +08:00
|
|
|
void SwitchInst::growOperands() {
|
2008-05-10 16:32:32 +08:00
|
|
|
unsigned e = getNumOperands();
|
2011-04-01 16:00:58 +08:00
|
|
|
unsigned NumOps = e*3;
|
2005-01-29 08:35:16 +08:00
|
|
|
|
|
|
|
ReservedSpace = NumOps;
|
2015-06-11 06:38:41 +08:00
|
|
|
growHungoffUses(ReservedSpace);
|
2005-01-29 08:35:16 +08:00
|
|
|
}
|
|
|
|
|
2009-10-28 03:13:16 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2011-01-16 23:30:52 +08:00
|
|
|
// IndirectBrInst Implementation
|
2009-10-28 03:13:16 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-10-28 08:19:10 +08:00
|
|
|
void IndirectBrInst::init(Value *Address, unsigned NumDests) {
|
2010-02-16 19:11:14 +08:00
|
|
|
assert(Address && Address->getType()->isPointerTy() &&
|
2009-10-29 13:53:32 +08:00
|
|
|
"Address of indirectbr must be a pointer");
|
2009-10-28 03:13:16 +08:00
|
|
|
ReservedSpace = 1+NumDests;
|
2015-06-13 01:48:10 +08:00
|
|
|
setNumHungOffUseOperands(1);
|
2015-06-11 06:38:46 +08:00
|
|
|
allocHungoffUses(ReservedSpace);
|
|
|
|
|
2015-05-22 06:48:54 +08:00
|
|
|
Op<0>() = Address;
|
2009-10-28 03:13:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-01 16:00:58 +08:00
|
|
|
/// 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.
|
2009-10-28 03:13:16 +08:00
|
|
|
///
|
2011-04-01 16:00:58 +08:00
|
|
|
void IndirectBrInst::growOperands() {
|
2009-10-28 03:13:16 +08:00
|
|
|
unsigned e = getNumOperands();
|
2011-04-01 16:00:58 +08:00
|
|
|
unsigned NumOps = e*2;
|
2009-10-28 03:13:16 +08:00
|
|
|
|
|
|
|
ReservedSpace = NumOps;
|
2015-06-11 06:38:41 +08:00
|
|
|
growHungoffUses(ReservedSpace);
|
2009-10-28 03:13:16 +08:00
|
|
|
}
|
|
|
|
|
2009-10-28 08:19:10 +08:00
|
|
|
IndirectBrInst::IndirectBrInst(Value *Address, unsigned NumCases,
|
|
|
|
Instruction *InsertBefore)
|
|
|
|
: TerminatorInst(Type::getVoidTy(Address->getContext()),Instruction::IndirectBr,
|
2014-04-09 14:08:46 +08:00
|
|
|
nullptr, 0, InsertBefore) {
|
2009-10-28 03:13:16 +08:00
|
|
|
init(Address, NumCases);
|
|
|
|
}
|
|
|
|
|
2009-10-28 08:19:10 +08:00
|
|
|
IndirectBrInst::IndirectBrInst(Value *Address, unsigned NumCases,
|
|
|
|
BasicBlock *InsertAtEnd)
|
|
|
|
: TerminatorInst(Type::getVoidTy(Address->getContext()),Instruction::IndirectBr,
|
2014-04-09 14:08:46 +08:00
|
|
|
nullptr, 0, InsertAtEnd) {
|
2009-10-28 03:13:16 +08:00
|
|
|
init(Address, NumCases);
|
|
|
|
}
|
|
|
|
|
2009-10-28 08:19:10 +08:00
|
|
|
IndirectBrInst::IndirectBrInst(const IndirectBrInst &IBI)
|
2015-06-11 06:38:46 +08:00
|
|
|
: TerminatorInst(Type::getVoidTy(IBI.getContext()), Instruction::IndirectBr,
|
|
|
|
nullptr, IBI.getNumOperands()) {
|
|
|
|
allocHungoffUses(IBI.getNumOperands());
|
2015-06-13 01:48:05 +08:00
|
|
|
Use *OL = getOperandList();
|
|
|
|
const Use *InOL = IBI.getOperandList();
|
2009-10-28 03:13:16 +08:00
|
|
|
for (unsigned i = 0, E = IBI.getNumOperands(); i != E; ++i)
|
|
|
|
OL[i] = InOL[i];
|
|
|
|
SubclassOptionalData = IBI.SubclassOptionalData;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// addDestination - Add a destination.
|
|
|
|
///
|
2009-10-28 08:19:10 +08:00
|
|
|
void IndirectBrInst::addDestination(BasicBlock *DestBB) {
|
2015-06-13 01:48:10 +08:00
|
|
|
unsigned OpNo = getNumOperands();
|
2009-10-28 03:13:16 +08:00
|
|
|
if (OpNo+1 > ReservedSpace)
|
2011-04-01 16:00:58 +08:00
|
|
|
growOperands(); // Get more space!
|
2009-10-28 03:13:16 +08:00
|
|
|
// Initialize some new operands.
|
|
|
|
assert(OpNo < ReservedSpace && "Growing didn't work!");
|
2015-06-13 01:48:10 +08:00
|
|
|
setNumHungOffUseOperands(OpNo+1);
|
2015-06-13 01:48:05 +08:00
|
|
|
getOperandList()[OpNo] = DestBB;
|
2009-10-28 03:13:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// removeDestination - This method removes the specified successor from the
|
2009-10-28 08:19:10 +08:00
|
|
|
/// indirectbr instruction.
|
|
|
|
void IndirectBrInst::removeDestination(unsigned idx) {
|
2009-10-28 03:13:16 +08:00
|
|
|
assert(idx < getNumOperands()-1 && "Successor index out of range!");
|
|
|
|
|
|
|
|
unsigned NumOps = getNumOperands();
|
2015-06-13 01:48:05 +08:00
|
|
|
Use *OL = getOperandList();
|
2009-10-28 03:13:16 +08:00
|
|
|
|
|
|
|
// Replace this value with the last one.
|
|
|
|
OL[idx+1] = OL[NumOps-1];
|
|
|
|
|
|
|
|
// Nuke the last value.
|
2014-04-09 14:08:46 +08:00
|
|
|
OL[NumOps-1].set(nullptr);
|
2015-06-13 01:48:10 +08:00
|
|
|
setNumHungOffUseOperands(NumOps-1);
|
2009-10-28 03:13:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
2015-06-25 04:22:23 +08:00
|
|
|
// cloneImpl() implementations
|
2009-10-28 03:13:16 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2004-10-16 07:52:53 +08:00
|
|
|
// Define these methods here so vtables don't get emitted into every translation
|
|
|
|
// unit that uses these classes.
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
GetElementPtrInst *GetElementPtrInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new (getNumOperands()) GetElementPtrInst(*this);
|
2004-10-16 07:52:53 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
BinaryOperator *BinaryOperator::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return Create(getOpcode(), Op<0>(), Op<1>());
|
2004-10-16 07:52:53 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
FCmpInst *FCmpInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new FCmpInst(getPredicate(), Op<0>(), Op<1>());
|
2006-11-20 09:22:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
ICmpInst *ICmpInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new ICmpInst(getPredicate(), Op<0>(), Op<1>());
|
2008-05-23 08:36:11 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
ExtractValueInst *ExtractValueInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new ExtractValueInst(*this);
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
InsertValueInst *InsertValueInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new InsertValueInst(*this);
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
AllocaInst *AllocaInst::cloneImpl() const {
|
2014-05-01 00:12:21 +08:00
|
|
|
AllocaInst *Result = new AllocaInst(getAllocatedType(),
|
2017-04-11 06:27:50 +08:00
|
|
|
getType()->getAddressSpace(),
|
2014-05-01 00:12:21 +08:00
|
|
|
(Value *)getOperand(0), getAlignment());
|
|
|
|
Result->setUsedWithInAlloca(isUsedWithInAlloca());
|
2016-04-02 05:41:15 +08:00
|
|
|
Result->setSwiftError(isSwiftError());
|
2014-05-01 00:12:21 +08:00
|
|
|
return Result;
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
LoadInst *LoadInst::cloneImpl() const {
|
2011-08-10 07:02:53 +08:00
|
|
|
return new LoadInst(getOperand(0), Twine(), isVolatile(),
|
2017-07-12 06:23:00 +08:00
|
|
|
getAlignment(), getOrdering(), getSyncScopeID());
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
StoreInst *StoreInst::cloneImpl() const {
|
2011-08-11 01:39:11 +08:00
|
|
|
return new StoreInst(getOperand(0), getOperand(1), isVolatile(),
|
2017-07-12 06:23:00 +08:00
|
|
|
getAlignment(), getOrdering(), getSyncScopeID());
|
2011-08-10 07:02:53 +08:00
|
|
|
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
AtomicCmpXchgInst *AtomicCmpXchgInst::cloneImpl() const {
|
2011-07-29 05:48:00 +08:00
|
|
|
AtomicCmpXchgInst *Result =
|
|
|
|
new AtomicCmpXchgInst(getOperand(0), getOperand(1), getOperand(2),
|
2014-03-11 18:48:52 +08:00
|
|
|
getSuccessOrdering(), getFailureOrdering(),
|
2017-07-12 06:23:00 +08:00
|
|
|
getSyncScopeID());
|
2011-07-29 05:48:00 +08:00
|
|
|
Result->setVolatile(isVolatile());
|
IR: add "cmpxchg weak" variant to support permitted failure.
This commit adds a weak variant of the cmpxchg operation, as described
in C++11. A cmpxchg instruction with this modifier is permitted to
fail to store, even if the comparison indicated it should.
As a result, cmpxchg instructions must return a flag indicating
success in addition to their original iN value loaded. Thus, for
uniformity *all* cmpxchg instructions now return "{ iN, i1 }". The
second flag is 1 when the store succeeded.
At the DAG level, a new ATOMIC_CMP_SWAP_WITH_SUCCESS node has been
added as the natural representation for the new cmpxchg instructions.
It is a strong cmpxchg.
By default this gets Expanded to the existing ATOMIC_CMP_SWAP during
Legalization, so existing backends should see no change in behaviour.
If they wish to deal with the enhanced node instead, they can call
setOperationAction on it. Beware: as a node with 2 results, it cannot
be selected from TableGen.
Currently, no use is made of the extra information provided in this
patch. Test updates are almost entirely adapting the input IR to the
new scheme.
Summary for out of tree users:
------------------------------
+ Legacy Bitcode files are upgraded during read.
+ Legacy assembly IR files will be invalid.
+ Front-ends must adapt to different type for "cmpxchg".
+ Backends should be unaffected by default.
llvm-svn: 210903
2014-06-13 22:24:07 +08:00
|
|
|
Result->setWeak(isWeak());
|
2011-07-29 05:48:00 +08:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
AtomicRMWInst *AtomicRMWInst::cloneImpl() const {
|
2011-07-29 05:48:00 +08:00
|
|
|
AtomicRMWInst *Result =
|
2017-07-12 06:23:00 +08:00
|
|
|
new AtomicRMWInst(getOperation(), getOperand(0), getOperand(1),
|
|
|
|
getOrdering(), getSyncScopeID());
|
2011-07-29 05:48:00 +08:00
|
|
|
Result->setVolatile(isVolatile());
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
FenceInst *FenceInst::cloneImpl() const {
|
2017-07-12 06:23:00 +08:00
|
|
|
return new FenceInst(getContext(), getOrdering(), getSyncScopeID());
|
2011-07-26 07:16:38 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
TruncInst *TruncInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new TruncInst(getOperand(0), getType());
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
ZExtInst *ZExtInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new ZExtInst(getOperand(0), getType());
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
SExtInst *SExtInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new SExtInst(getOperand(0), getType());
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
FPTruncInst *FPTruncInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new FPTruncInst(getOperand(0), getType());
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
FPExtInst *FPExtInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new FPExtInst(getOperand(0), getType());
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
2008-05-23 08:36:11 +08:00
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
UIToFPInst *UIToFPInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new UIToFPInst(getOperand(0), getType());
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
SIToFPInst *SIToFPInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new SIToFPInst(getOperand(0), getType());
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
FPToUIInst *FPToUIInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new FPToUIInst(getOperand(0), getType());
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
FPToSIInst *FPToSIInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new FPToSIInst(getOperand(0), getType());
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
PtrToIntInst *PtrToIntInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new PtrToIntInst(getOperand(0), getType());
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
IntToPtrInst *IntToPtrInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new IntToPtrInst(getOperand(0), getType());
|
2008-05-15 18:04:30 +08:00
|
|
|
}
|
2009-07-10 07:48:35 +08:00
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
BitCastInst *BitCastInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new BitCastInst(getOperand(0), getType());
|
2008-05-15 18:04:30 +08:00
|
|
|
}
|
2006-11-27 09:05:10 +08:00
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
AddrSpaceCastInst *AddrSpaceCastInst::cloneImpl() const {
|
2013-11-15 09:34:59 +08:00
|
|
|
return new AddrSpaceCastInst(getOperand(0), getType());
|
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
CallInst *CallInst::cloneImpl() const {
|
2015-11-11 04:13:21 +08:00
|
|
|
if (hasOperandBundles()) {
|
|
|
|
unsigned DescriptorBytes = getNumOperandBundles() * sizeof(BundleOpInfo);
|
|
|
|
return new(getNumOperands(), DescriptorBytes) CallInst(*this);
|
|
|
|
}
|
2009-10-28 06:16:29 +08:00
|
|
|
return new(getNumOperands()) CallInst(*this);
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
SelectInst *SelectInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return SelectInst::Create(getOperand(0), getOperand(1), getOperand(2));
|
2006-04-08 09:18:18 +08:00
|
|
|
}
|
2009-07-10 07:48:35 +08:00
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
VAArgInst *VAArgInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new VAArgInst(getOperand(0), getType());
|
2006-04-08 09:18:18 +08:00
|
|
|
}
|
2009-07-10 07:48:35 +08:00
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
ExtractElementInst *ExtractElementInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return ExtractElementInst::Create(getOperand(0), getOperand(1));
|
2006-04-08 09:18:18 +08:00
|
|
|
}
|
2009-07-10 07:48:35 +08:00
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
InsertElementInst *InsertElementInst::cloneImpl() const {
|
2012-01-26 07:49:49 +08:00
|
|
|
return InsertElementInst::Create(getOperand(0), getOperand(1), getOperand(2));
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
ShuffleVectorInst *ShuffleVectorInst::cloneImpl() const {
|
2012-01-26 07:49:49 +08:00
|
|
|
return new ShuffleVectorInst(getOperand(0), getOperand(1), getOperand(2));
|
2008-05-15 18:04:30 +08:00
|
|
|
}
|
2009-07-10 07:48:35 +08:00
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
PHINode *PHINode::cloneImpl() const { return new PHINode(*this); }
|
2009-10-28 06:16:29 +08:00
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
LandingPadInst *LandingPadInst::cloneImpl() const {
|
2011-08-13 04:24:12 +08:00
|
|
|
return new LandingPadInst(*this);
|
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
ReturnInst *ReturnInst::cloneImpl() const {
|
2009-10-28 06:16:29 +08:00
|
|
|
return new(getNumOperands()) ReturnInst(*this);
|
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
BranchInst *BranchInst::cloneImpl() const {
|
2011-01-08 04:29:02 +08:00
|
|
|
return new(getNumOperands()) BranchInst(*this);
|
2008-05-15 18:04:30 +08:00
|
|
|
}
|
2009-07-10 07:48:35 +08:00
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
SwitchInst *SwitchInst::cloneImpl() const { return new SwitchInst(*this); }
|
2009-07-10 07:48:35 +08:00
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
IndirectBrInst *IndirectBrInst::cloneImpl() const {
|
2009-10-28 08:19:10 +08:00
|
|
|
return new IndirectBrInst(*this);
|
2009-10-28 03:13:16 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
InvokeInst *InvokeInst::cloneImpl() const {
|
2015-11-11 04:13:21 +08:00
|
|
|
if (hasOperandBundles()) {
|
|
|
|
unsigned DescriptorBytes = getNumOperandBundles() * sizeof(BundleOpInfo);
|
|
|
|
return new(getNumOperands(), DescriptorBytes) InvokeInst(*this);
|
|
|
|
}
|
2009-10-28 06:16:29 +08:00
|
|
|
return new(getNumOperands()) InvokeInst(*this);
|
2008-05-15 18:04:30 +08:00
|
|
|
}
|
2009-07-10 07:48:35 +08:00
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
ResumeInst *ResumeInst::cloneImpl() const { return new (1) ResumeInst(*this); }
|
2011-07-31 14:30:59 +08:00
|
|
|
|
2015-08-01 01:58:14 +08:00
|
|
|
CleanupReturnInst *CleanupReturnInst::cloneImpl() const {
|
|
|
|
return new (getNumOperands()) CleanupReturnInst(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
CatchReturnInst *CatchReturnInst::cloneImpl() const {
|
2015-08-15 10:46:08 +08:00
|
|
|
return new (getNumOperands()) CatchReturnInst(*this);
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
CatchSwitchInst *CatchSwitchInst::cloneImpl() const {
|
|
|
|
return new CatchSwitchInst(*this);
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
[IR] Reformulate LLVM's EH funclet IR
While we have successfully implemented a funclet-oriented EH scheme on
top of LLVM IR, our scheme has some notable deficiencies:
- catchendpad and cleanupendpad are necessary in the current design
but they are difficult to explain to others, even to seasoned LLVM
experts.
- catchendpad and cleanupendpad are optimization barriers. They cannot
be split and force all potentially throwing call-sites to be invokes.
This has a noticable effect on the quality of our code generation.
- catchpad, while similar in some aspects to invoke, is fairly awkward.
It is unsplittable, starts a funclet, and has control flow to other
funclets.
- The nesting relationship between funclets is currently a property of
control flow edges. Because of this, we are forced to carefully
analyze the flow graph to see if there might potentially exist illegal
nesting among funclets. While we have logic to clone funclets when
they are illegally nested, it would be nicer if we had a
representation which forbade them upfront.
Let's clean this up a bit by doing the following:
- Instead, make catchpad more like cleanuppad and landingpad: no control
flow, just a bunch of simple operands; catchpad would be splittable.
- Introduce catchswitch, a control flow instruction designed to model
the constraints of funclet oriented EH.
- Make funclet scoping explicit by having funclet instructions consume
the token produced by the funclet which contains them.
- Remove catchendpad and cleanupendpad. Their presence can be inferred
implicitly using coloring information.
N.B. The state numbering code for the CLR has been updated but the
veracity of it's output cannot be spoken for. An expert should take a
look to make sure the results are reasonable.
Reviewers: rnk, JosephTremoulet, andrew.w.kaylor
Differential Revision: http://reviews.llvm.org/D15139
llvm-svn: 255422
2015-12-12 13:38:55 +08:00
|
|
|
FuncletPadInst *FuncletPadInst::cloneImpl() const {
|
|
|
|
return new (getNumOperands()) FuncletPadInst(*this);
|
2015-08-01 01:58:14 +08:00
|
|
|
}
|
|
|
|
|
2015-06-25 04:22:23 +08:00
|
|
|
UnreachableInst *UnreachableInst::cloneImpl() const {
|
2009-09-27 15:38:41 +08:00
|
|
|
LLVMContext &Context = getContext();
|
2009-10-28 06:16:29 +08:00
|
|
|
return new UnreachableInst(Context);
|
2009-07-10 07:48:35 +08:00
|
|
|
}
|