#include <cmath>
using namespace llvm;
-static cl::opt<bool>
-NoBuiltin("no-builtin", cl::init(false),
- cl::desc("Don't recognize built-in functions that do not begin "
- "with `__builtin_' as prefix"));
-
/// makeVTList - Return an instance of the SDVTList struct initialized with the
/// specified members.
static SDVTList makeVTList(const MVT *VTs, unsigned NumVTs) {
// convert modifies in place, so make a copy.
APFloat Val2 = APFloat(Val);
- return Val2.convert(*MVTToAPFloatSemantics(VT),
- APFloat::rmNearestTiesToEven) == APFloat::opOK;
+ bool losesInfo;
+ (void) Val2.convert(*MVTToAPFloatSemantics(VT), APFloat::rmNearestTiesToEven,
+ &losesInfo);
+ return !losesInfo;
}
//===----------------------------------------------------------------------===//
return false;
} else if (isa<ConstantFPSDNode>(NotZero)) {
if (!cast<ConstantFPSDNode>(NotZero)->getValueAPF().
- convertToAPInt().isAllOnesValue())
+ bitcastToAPInt().isAllOnesValue())
return false;
} else
return false;
unsigned OldG = (Operation >> 1) & 1;
return ISD::CondCode((Operation & ~6) | // Keep the N, U, E bits
(OldL << 1) | // New G bit
- (OldG << 2)); // New L bit.
+ (OldG << 2)); // New L bit.
}
/// getSetCCInverse - Return the operation corresponding to !(X op Y), where
Operation ^= 7; // Flip L, G, E bits, but not U.
else
Operation ^= 15; // Flip all of the condition bits.
+
if (Operation > ISD::SETTRUE2)
- Operation &= ~8; // Don't let N and U bits get set.
+ Operation &= ~8; // Don't let N and U bits get set.
+
return ISD::CondCode(Operation);
}
/// encodeMemSDNodeFlags - Generic routine for computing a value for use in
/// the CSE map that carries both alignment and volatility information.
///
-static unsigned encodeMemSDNodeFlags(bool isVolatile, unsigned Alignment) {
+static inline unsigned
+encodeMemSDNodeFlags(bool isVolatile, unsigned Alignment) {
return isVolatile | ((Log2_32(Alignment) + 1) << 1);
}
if (Operand->use_empty())
DeadNodes.push_back(Operand);
}
- if (N->OperandsNeedDelete) {
+
+ if (N->OperandsNeedDelete)
delete[] N->OperandList;
- }
+
N->OperandList = 0;
N->NumOperands = 0;
}
void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) {
-
// Drop all of the operands and decrement used node's use counts.
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
I->getVal()->removeUser(std::distance(N->op_begin(), I), N);
- if (N->OperandsNeedDelete)
+
+ if (N->OperandsNeedDelete) {
delete[] N->OperandList;
+ N->OperandList = 0;
+ }
assert(N != AllNodes.begin());
NodeAllocator.Deallocate(AllNodes.remove(N));
case ISD::DBG_STOPPOINT:
case ISD::EH_LABEL:
case ISD::DECLARE:
- return 0; // Never add these nodes.
+ return 0; // Never add these nodes.
}
// Check that remaining values produced are not flags.
for (unsigned i = 1, e = N->getNumValues(); i != e; ++i)
if (N->getValueType(i) == MVT::Flag)
- return 0; // Never CSE anything that produces a flag.
+ return 0; // Never CSE anything that produces a flag.
SDNode *New = CSEMap.GetOrInsertNode(N);
if (New != N) return New; // Node already existed.
case ISD::DBG_LABEL:
case ISD::DBG_STOPPOINT:
case ISD::EH_LABEL:
- return 0; // Never add these nodes.
+ return 0; // Never add these nodes.
}
// Check that remaining values produced are not flags.
for (unsigned i = 1, e = N->getNumValues(); i != e; ++i)
if (N->getValueType(i) == MVT::Flag)
- return 0; // Never CSE anything that produces a flag.
+ return 0; // Never CSE anything that produces a flag.
SDValue Ops[] = { Op };
FoldingSetNodeID ID;
// Check that remaining values produced are not flags.
for (unsigned i = 1, e = N->getNumValues(); i != e; ++i)
if (N->getValueType(i) == MVT::Flag)
- return 0; // Never CSE anything that produces a flag.
+ return 0; // Never CSE anything that produces a flag.
SDValue Ops[] = { Op1, Op2 };
FoldingSetNodeID ID;
case ISD::DBG_STOPPOINT:
case ISD::EH_LABEL:
case ISD::DECLARE:
- return 0; // Never add these nodes.
+ return 0; // Never add these nodes.
}
// Check that remaining values produced are not flags.
for (unsigned i = 1, e = N->getNumValues(); i != e; ++i)
if (N->getValueType(i) == MVT::Flag)
- return 0; // Never CSE anything that produces a flag.
+ return 0; // Never CSE anything that produces a flag.
FoldingSetNodeID ID;
AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops, NumOps);
assert(N->getValueType(0).isVector() && "Wrong BUILD_VECTOR return type!");
assert(N->getNumOperands() == N->getValueType(0).getVectorNumElements() &&
"Wrong number of BUILD_VECTOR operands!");
- MVT EltVT = N->getValueType(0).getVectorElementType();
- for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
- assert(I->getSDValue().getValueType() == EltVT &&
- "Wrong BUILD_VECTOR operand type!");
+ // FIXME: Change vector_shuffle to a variadic node with mask elements being
+ // operands of the node. Currently the mask is a BUILD_VECTOR passed as an
+ // operand, and it is not always possible to legalize it. Turning off the
+ // following checks at least makes it possible to legalize most of the time.
+// MVT EltVT = N->getValueType(0).getVectorElementType();
+// for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
+// assert(I->getSDValue().getValueType() == EltVT &&
+// "Wrong BUILD_VECTOR operand type!");
break;
}
}
while (!AllNodes.empty()) {
SDNode *N = AllNodes.remove(AllNodes.begin());
N->SetNextInBucket(0);
- if (N->OperandsNeedDelete)
+
+ if (N->OperandsNeedDelete) {
delete [] N->OperandList;
+ N->OperandList = 0;
+ }
+
NodeAllocator.Deallocate(N);
}
}
}
SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV,
- MVT VT, int Offset,
+ MVT VT, int64_t Offset,
bool isTargetGA) {
unsigned Opc;
+ // Truncate (with sign-extension) the offset value to the pointer size.
+ unsigned BitWidth = TLI.getPointerTy().getSizeInBits();
+ if (BitWidth < 64)
+ Offset = (Offset << (64 - BitWidth) >> (64 - BitWidth));
+
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
if (!GVar) {
// If GV is an alias then use the aliasee for determining thread-localness.
bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const {
GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op);
if (!GA) return false;
+ if (GA->getOffset() != 0) return false;
GlobalVariable *GV = dyn_cast<GlobalVariable>(GA->getGlobal());
if (!GV) return false;
MachineModuleInfo *MMI = getMachineModuleInfo();
V.clearSign();
return getConstantFP(V, VT);
case ISD::FP_ROUND:
- case ISD::FP_EXTEND:
+ case ISD::FP_EXTEND: {
+ bool ignored;
// This can return overflow, underflow, or inexact; we don't care.
// FIXME need to be more flexible about rounding mode.
(void)V.convert(*MVTToAPFloatSemantics(VT),
- APFloat::rmNearestTiesToEven);
+ APFloat::rmNearestTiesToEven, &ignored);
return getConstantFP(V, VT);
+ }
case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT: {
integerPart x;
+ bool ignored;
assert(integerPartWidth >= 64);
// FIXME need to be more flexible about rounding mode.
APFloat::opStatus s = V.convertToInteger(&x, 64U,
Opcode==ISD::FP_TO_SINT,
- APFloat::rmTowardZero);
+ APFloat::rmTowardZero, &ignored);
if (s==APFloat::opInvalidOp) // inexact is OK, in fact usual
break;
return getConstant(x, VT);
}
case ISD::BIT_CONVERT:
if (VT == MVT::i32 && C->getValueType(0) == MVT::f32)
- return getConstant((uint32_t)V.convertToAPInt().getZExtValue(), VT);
+ return getConstant((uint32_t)V.bitcastToAPInt().getZExtValue(), VT);
else if (VT == MVT::i64 && C->getValueType(0) == MVT::f64)
- return getConstant(V.convertToAPInt().getZExtValue(), VT);
+ return getConstant(V.bitcastToAPInt().getZExtValue(), VT);
break;
}
}
// Fold trivial token factors.
if (N1.getOpcode() == ISD::EntryToken) return N2;
if (N2.getOpcode() == ISD::EntryToken) return N1;
+ if (N1 == N2) return N1;
break;
case ISD::CONCAT_VECTORS:
// A CONCAT_VECTOR with all operands BUILD_VECTOR can be simplified to
// Expand memcpy to a series of load and store ops if the size operand falls
// below a certain threshold.
std::vector<MVT> MemOps;
- uint64_t Limit = -1;
+ uint64_t Limit = -1ULL;
if (!AlwaysInline)
Limit = TLI.getMaxStoresPerMemcpy();
unsigned DstAlign = Align; // Destination alignment can change.
// Expand memmove to a series of load and store ops if the size operand falls
// below a certain threshold.
std::vector<MVT> MemOps;
- uint64_t Limit = -1;
+ uint64_t Limit = -1ULL;
if (!AlwaysInline)
Limit = TLI.getMaxStoresPerMemmove();
unsigned DstAlign = Align; // Destination alignment can change.
// code. If the target chooses to do this, this is the next best.
SDValue Result =
TLI.EmitTargetCodeForMemset(*this, Chain, Dst, Src, Size, Align,
- DstSV, DstSVOff, NoBuiltin);
+ DstSV, DstSVOff);
if (Result.getNode())
return Result;
return getNode(ISD::MERGE_VALUES, getVTList(&VTs[0], NumOps), Ops, NumOps);
}
+SDValue
+SelectionDAG::getMemIntrinsicNode(unsigned Opcode,
+ const MVT *VTs, unsigned NumVTs,
+ const SDValue *Ops, unsigned NumOps,
+ MVT MemVT, const Value *srcValue, int SVOff,
+ unsigned Align, bool Vol,
+ bool ReadMem, bool WriteMem) {
+ return getMemIntrinsicNode(Opcode, makeVTList(VTs, NumVTs), Ops, NumOps,
+ MemVT, srcValue, SVOff, Align, Vol,
+ ReadMem, WriteMem);
+}
+
+SDValue
+SelectionDAG::getMemIntrinsicNode(unsigned Opcode, SDVTList VTList,
+ const SDValue *Ops, unsigned NumOps,
+ MVT MemVT, const Value *srcValue, int SVOff,
+ unsigned Align, bool Vol,
+ bool ReadMem, bool WriteMem) {
+ // Memoize the node unless it returns a flag.
+ MemIntrinsicSDNode *N;
+ if (VTList.VTs[VTList.NumVTs-1] != MVT::Flag) {
+ FoldingSetNodeID ID;
+ AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps);
+ void *IP = 0;
+ if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
+ return SDValue(E, 0);
+
+ N = NodeAllocator.Allocate<MemIntrinsicSDNode>();
+ new (N) MemIntrinsicSDNode(Opcode, VTList, Ops, NumOps, MemVT,
+ srcValue, SVOff, Align, Vol, ReadMem, WriteMem);
+ CSEMap.InsertNode(N, IP);
+ } else {
+ N = NodeAllocator.Allocate<MemIntrinsicSDNode>();
+ new (N) MemIntrinsicSDNode(Opcode, VTList, Ops, NumOps, MemVT,
+ srcValue, SVOff, Align, Vol, ReadMem, WriteMem);
+ }
+ AllNodes.push_back(N);
+ return SDValue(N, 0);
+}
+
SDValue
SelectionDAG::getCall(unsigned CallingConv, bool IsVarArgs, bool IsTailCall,
bool IsInreg, SDVTList VTs,
if (NumOps > N->NumOperands) {
if (N->OperandsNeedDelete)
delete[] N->OperandList;
+
if (N->isMachineOpcode()) {
// We're creating a final node that will live unmorphed for the
// remainder of the current SelectionDAG iteration, so we can allocate
void LoadSDNode::ANCHOR() {}
void StoreSDNode::ANCHOR() {}
void AtomicSDNode::ANCHOR() {}
+void MemIntrinsicSDNode::ANCHOR() {}
void CallSDNode::ANCHOR() {}
HandleSDNode::~HandleSDNode() {
}
GlobalAddressSDNode::GlobalAddressSDNode(bool isTarget, const GlobalValue *GA,
- MVT VT, int o)
+ MVT VT, int64_t o)
: SDNode(isa<GlobalVariable>(GA) &&
cast<GlobalVariable>(GA)->isThreadLocal() ?
// Thread Local
assert(isVolatile() == vol && "Volatile representation error!");
}
+MemSDNode::MemSDNode(unsigned Opc, SDVTList VTs, const SDValue *Ops,
+ unsigned NumOps, MVT memvt, const Value *srcValue,
+ int SVO, unsigned alignment, bool vol)
+ : SDNode(Opc, VTs, Ops, NumOps),
+ MemoryVT(memvt), SrcValue(srcValue), SVOffset(SVO),
+ Flags(vol | ((Log2_32(alignment) + 1) << 1)) {
+ assert(isPowerOf2_32(alignment) && "Alignment is not a power of 2!");
+ assert(getAlignment() == alignment && "Alignment representation error!");
+ assert(isVolatile() == vol && "Volatile representation error!");
+}
+
/// getMemOperand - Return a MachineMemOperand object describing the memory
/// reference performed by this memory reference.
MachineMemOperand MemSDNode::getMemOperand() const {
Flags = MachineMemOperand::MOLoad;
else if (isa<StoreSDNode>(this))
Flags = MachineMemOperand::MOStore;
- else {
- assert(isa<AtomicSDNode>(this) && "Unknown MemSDNode opcode!");
+ else if (isa<AtomicSDNode>(this)) {
Flags = MachineMemOperand::MOLoad | MachineMemOperand::MOStore;
}
+ else {
+ const MemIntrinsicSDNode* MemIntrinNode = dyn_cast<MemIntrinsicSDNode>(this);
+ assert(MemIntrinNode && "Unknown MemSDNode opcode!");
+ if (MemIntrinNode->readMem()) Flags |= MachineMemOperand::MOLoad;
+ if (MemIntrinNode->writeMem()) Flags |= MachineMemOperand::MOStore;
+ }
int Size = (getMemoryVT().getSizeInBits() + 7) >> 3;
if (isVolatile()) Flags |= MachineMemOperand::MOVolatile;
OS << '<' << CSDN->getValueAPF().convertToDouble() << '>';
else {
OS << "<APFloat(";
- CSDN->getValueAPF().convertToAPInt().dump();
+ CSDN->getValueAPF().bitcastToAPInt().dump();
OS << ")>";
}
} else if (const GlobalAddressSDNode *GADN =
dyn_cast<GlobalAddressSDNode>(this)) {
- int offset = GADN->getOffset();
+ int64_t offset = GADN->getOffset();
OS << '<';
WriteAsOperand(OS, GADN->getGlobal());
OS << '>';