#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SetVector.h"
// 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 nodes use counts.
+ // 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.
SDValue SelectionDAG::getConstantPool(Constant *C, MVT VT,
unsigned Alignment, int Offset,
bool isTarget) {
+ if (Alignment == 0)
+ Alignment =
+ TLI.getTargetData()->getPreferredTypeAlignmentShift(C->getType());
unsigned Opc = isTarget ? ISD::TargetConstantPool : ISD::ConstantPool;
FoldingSetNodeID ID;
AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0);
SDValue SelectionDAG::getConstantPool(MachineConstantPoolValue *C, MVT VT,
unsigned Alignment, int Offset,
bool isTarget) {
+ if (Alignment == 0)
+ Alignment =
+ TLI.getTargetData()->getPreferredTypeAlignmentShift(C->getType());
unsigned Opc = isTarget ? ISD::TargetConstantPool : ISD::ConstantPool;
FoldingSetNodeID ID;
AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0);
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;
}
}
return SDValue(N, 0);
}
+SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode,
+ MVT VT,
+ ConstantSDNode *Cst1,
+ ConstantSDNode *Cst2) {
+ const APInt &C1 = Cst1->getAPIntValue(), &C2 = Cst2->getAPIntValue();
+
+ switch (Opcode) {
+ case ISD::ADD: return getConstant(C1 + C2, VT);
+ case ISD::SUB: return getConstant(C1 - C2, VT);
+ case ISD::MUL: return getConstant(C1 * C2, VT);
+ case ISD::UDIV:
+ if (C2.getBoolValue()) return getConstant(C1.udiv(C2), VT);
+ break;
+ case ISD::UREM:
+ if (C2.getBoolValue()) return getConstant(C1.urem(C2), VT);
+ break;
+ case ISD::SDIV:
+ if (C2.getBoolValue()) return getConstant(C1.sdiv(C2), VT);
+ break;
+ case ISD::SREM:
+ if (C2.getBoolValue()) return getConstant(C1.srem(C2), VT);
+ break;
+ case ISD::AND: return getConstant(C1 & C2, VT);
+ case ISD::OR: return getConstant(C1 | C2, VT);
+ case ISD::XOR: return getConstant(C1 ^ C2, VT);
+ case ISD::SHL: return getConstant(C1 << C2, VT);
+ case ISD::SRL: return getConstant(C1.lshr(C2), VT);
+ case ISD::SRA: return getConstant(C1.ashr(C2), VT);
+ case ISD::ROTL: return getConstant(C1.rotl(C2), VT);
+ case ISD::ROTR: return getConstant(C1.rotr(C2), VT);
+ default: break;
+ }
+
+ return SDValue();
+}
+
SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT,
SDValue N1, SDValue N2) {
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.getNode());
// 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
if (N1C) {
if (N2C) {
- const APInt &C1 = N1C->getAPIntValue(), &C2 = N2C->getAPIntValue();
- switch (Opcode) {
- case ISD::ADD: return getConstant(C1 + C2, VT);
- case ISD::SUB: return getConstant(C1 - C2, VT);
- case ISD::MUL: return getConstant(C1 * C2, VT);
- case ISD::UDIV:
- if (C2.getBoolValue()) return getConstant(C1.udiv(C2), VT);
- break;
- case ISD::UREM :
- if (C2.getBoolValue()) return getConstant(C1.urem(C2), VT);
- break;
- case ISD::SDIV :
- if (C2.getBoolValue()) return getConstant(C1.sdiv(C2), VT);
- break;
- case ISD::SREM :
- if (C2.getBoolValue()) return getConstant(C1.srem(C2), VT);
- break;
- case ISD::AND : return getConstant(C1 & C2, VT);
- case ISD::OR : return getConstant(C1 | C2, VT);
- case ISD::XOR : return getConstant(C1 ^ C2, VT);
- case ISD::SHL : return getConstant(C1 << C2, VT);
- case ISD::SRL : return getConstant(C1.lshr(C2), VT);
- case ISD::SRA : return getConstant(C1.ashr(C2), VT);
- case ISD::ROTL : return getConstant(C1.rotl(C2), VT);
- case ISD::ROTR : return getConstant(C1.rotr(C2), VT);
- default: break;
- }
+ SDValue SV = FoldConstantArithmetic(Opcode, VT, N1C, N2C);
+ if (SV.getNode()) return SV;
} else { // Cannonicalize constant to RHS if commutative
if (isCommutativeBinOp(Opcode)) {
std::swap(N1C, N2C);
// 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.
Entry.Node = Size; Args.push_back(Entry);
std::pair<SDValue,SDValue> CallResult =
TLI.LowerCallTo(Chain, Type::VoidTy,
- false, false, false, CallingConv::C, false,
+ false, false, false, false, CallingConv::C, false,
getExternalSymbol("memcpy", TLI.getPointerTy()),
Args, *this);
return CallResult.second;
Entry.Node = Size; Args.push_back(Entry);
std::pair<SDValue,SDValue> CallResult =
TLI.LowerCallTo(Chain, Type::VoidTy,
- false, false, false, CallingConv::C, false,
+ false, false, false, false, CallingConv::C, false,
getExternalSymbol("memmove", TLI.getPointerTy()),
Args, *this);
return CallResult.second;
Args.push_back(Entry);
std::pair<SDValue,SDValue> CallResult =
TLI.LowerCallTo(Chain, Type::VoidTy,
- false, false, false, CallingConv::C, false,
+ false, false, false, false, CallingConv::C, false,
getExternalSymbol("memset", TLI.getPointerTy()),
Args, *this);
return CallResult.second;
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,
- SDVTList VTs,
+ bool IsInreg, SDVTList VTs,
const SDValue *Operands, unsigned NumOperands) {
// Do not include isTailCall in the folding set profile.
FoldingSetNodeID ID;
return SDValue(E, 0);
}
SDNode *N = NodeAllocator.Allocate<CallSDNode>();
- new (N) CallSDNode(CallingConv, IsVarArgs, IsTailCall,
+ new (N) CallSDNode(CallingConv, IsVarArgs, IsTailCall, IsInreg,
VTs, Operands, NumOperands);
CSEMap.InsertNode(N, IP);
AllNodes.push_back(N);
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
/// AssignTopologicalOrder - Assign a unique node id for each node in the DAG
/// based on their topological order. It returns the maximum id and a vector
/// of the SDNodes* in assigned order by reference.
-unsigned SelectionDAG::AssignTopologicalOrder(std::vector<SDNode*> &TopOrder) {
- unsigned DAGSize = AllNodes.size();
- std::vector<SDNode*> Sources;
+unsigned SelectionDAG::AssignTopologicalOrder() {
+
+ unsigned DAGSize = 0;
+
+ // SortedPos tracks the progress of the algorithm. Nodes before it are
+ // sorted, nodes after it are unsorted. When the algorithm completes
+ // it is at the end of the list.
+ allnodes_iterator SortedPos = allnodes_begin();
+
+ // Visit all the nodes. Add nodes with no operands to the TopOrder result
+ // array immediately. Annotate nodes that do have operands with their
+ // operand count. Before we do this, the Node Id fields of the nodes
+ // may contain arbitrary values. After, the Node Id fields for nodes
+ // before SortedPos will contain the topological sort index, and the
+ // Node Id fields for nodes At SortedPos and after will contain the
+ // count of outstanding operands.
+ for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ) {
+ SDNode *N = I++;
+ unsigned Degree = N->getNumOperands();
+ if (Degree == 0) {
+ // A node with no uses, add it to the result array immediately.
+ N->setNodeId(DAGSize++);
+ allnodes_iterator Q = N;
+ if (Q != SortedPos)
+ SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(Q));
+ ++SortedPos;
+ } else {
+ // Temporarily use the Node Id as scratch space for the degree count.
+ N->setNodeId(Degree);
+ }
+ }
- for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ++I){
+ // Visit all the nodes. As we iterate, moves nodes into sorted order,
+ // such that by the time the end is reached all nodes will be sorted.
+ for (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ++I) {
SDNode *N = I;
- unsigned Degree = N->use_size();
- // Temporarily use the Node Id as scratch space for the degree count.
- N->setNodeId(Degree);
- if (Degree == 0)
- Sources.push_back(N);
- }
-
- TopOrder.clear();
- TopOrder.reserve(DAGSize);
- int Id = 0;
- while (!Sources.empty()) {
- SDNode *N = Sources.back();
- Sources.pop_back();
- TopOrder.push_back(N);
- N->setNodeId(Id++);
- for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) {
- SDNode *P = I->getVal();
+ for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
+ UI != UE; ++UI) {
+ SDNode *P = *UI;
unsigned Degree = P->getNodeId();
--Degree;
- P->setNodeId(Degree);
- if (Degree == 0)
- Sources.push_back(P);
+ if (Degree == 0) {
+ // All of P's operands are sorted, so P may sorted now.
+ P->setNodeId(DAGSize++);
+ if (P != SortedPos)
+ SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(P));
+ ++SortedPos;
+ } else {
+ // Update P's outstanding operand count.
+ P->setNodeId(Degree);
+ }
}
}
- return Id;
+ assert(SortedPos == AllNodes.end() &&
+ "Topological sort incomplete!");
+ assert(AllNodes.front().getOpcode() == ISD::EntryToken &&
+ "First node in topological sort is not the entry token!");
+ assert(AllNodes.front().getNodeId() == 0 &&
+ "First node in topological sort has non-zero id!");
+ assert(AllNodes.front().getNumOperands() == 0 &&
+ "First node in topological sort has operands!");
+ assert(AllNodes.back().getNodeId() == (int)DAGSize-1 &&
+ "Last node in topologic sort has unexpected id!");
+ assert(AllNodes.back().use_empty() &&
+ "Last node in topologic sort has users!");
+ assert(DAGSize == allnodes_size() && "TopOrder result count mismatch!");
+ return DAGSize;
}
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 << '>';