Added support for machine specific constantpool values. These are useful for

representing expressions that can only be resolved at link time, etc.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30278 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2006-09-12 21:00:35 +00:00
parent cd5731d98b
commit d6594ae54c
11 changed files with 275 additions and 61 deletions

View File

@ -24,6 +24,7 @@ namespace llvm {
class ConstantArray;
class GlobalVariable;
class MachineConstantPoolEntry;
class MachineConstantPoolValue;
class Mangler;
class TargetAsmInfo;
@ -174,6 +175,8 @@ namespace llvm {
/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
///
void EmitGlobalConstant(const Constant* CV);
virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
/// printInlineAsm - This method formats and prints the specified machine
/// instruction that is an inline asm.
@ -188,7 +191,11 @@ namespace llvm {
/// printSetLabel - This method prints a set label for the specified
/// MachineBasicBlock
void printSetLabel(unsigned uid, const MachineBasicBlock *MBB) const;
/// printDataDirective - This method prints the asm directive for the
/// specified type.
void printDataDirective(const Type *type);
private:
void EmitXXStructorList(Constant *List);
void EmitConstantPool(unsigned Alignment, const char *Section,

View File

@ -15,22 +15,77 @@
#ifndef LLVM_CODEGEN_MACHINECONSTANTPOOL_H
#define LLVM_CODEGEN_MACHINECONSTANTPOOL_H
#include "llvm/CodeGen/SelectionDAGCSEMap.h"
#include <vector>
#include <iosfwd>
namespace llvm {
class AsmPrinter;
class Constant;
class TargetData;
class TargetMachine;
class MachineConstantPool;
/// Abstract base class for all machine specific constantpool value subclasses.
///
class MachineConstantPoolValue {
const Type *Ty;
public:
MachineConstantPoolValue(const Type *ty) : Ty(ty) {}
virtual ~MachineConstantPoolValue() {};
/// getType - get type of this MachineConstantPoolValue.
///
inline const Type *getType() const { return Ty; }
virtual int getExistingMachineCPValue(MachineConstantPool *CP,
unsigned Alignment) = 0;
virtual void AddSelectionDAGCSEId(SelectionDAGCSEMap::NodeID *Id) = 0;
/// print - Implement operator<<...
///
virtual void print(std::ostream &O) const = 0;
};
inline std::ostream &operator<<(std::ostream &OS,
const MachineConstantPoolValue &V) {
V.print(OS);
return OS;
}
/// This class is a data container for one entry in a MachineConstantPool.
/// It contains a pointer to the value and an offset from the start of
/// the constant pool.
/// @brief An entry in a MachineConstantPool
struct MachineConstantPoolEntry {
Constant *Val; ///< The constant itself.
unsigned Offset; ///< The offset of the constant from the start of the pool.
MachineConstantPoolEntry(Constant *V, unsigned O) : Val(V), Offset(O) {}
/// The constant itself.
union {
Constant *ConstVal;
MachineConstantPoolValue *MachineCPVal;
} Val;
/// The offset of the constant from the start of the pool. It's really
/// 31-bit only. The top bit is set when Val is a MachineConstantPoolValue.
unsigned Offset;
MachineConstantPoolEntry(Constant *V, unsigned O)
: Offset(O) {
assert((int)Offset >= 0 && "Offset is too large");
Val.ConstVal = V;
}
MachineConstantPoolEntry(MachineConstantPoolValue *V, unsigned O)
: Offset(O){
assert((int)Offset >= 0 && "Offset is too large");
Val.MachineCPVal = V;
Offset |= 1 << (sizeof(unsigned)*8-1);
}
bool isMachineConstantPoolEntry() const {
return (int)Offset < 0;
}
};
/// The MachineConstantPool class keeps track of constants referenced by a
@ -50,6 +105,7 @@ class MachineConstantPool {
public:
/// @brief The only constructor.
MachineConstantPool(const TargetData *td) : TD(td), PoolAlignment(1) {}
~MachineConstantPool();
/// getConstantPoolAlignment - Return the log2 of the alignment required by
/// the whole constant pool, of which the first element must be aligned.
@ -58,6 +114,7 @@ public:
/// getConstantPoolIndex - Create a new entry in the constant pool or return
/// an existing one. User must specify an alignment in bytes for the object.
unsigned getConstantPoolIndex(Constant *C, unsigned Alignment);
unsigned getConstantPoolIndex(MachineConstantPoolValue *V,unsigned Alignment);
/// isEmpty - Return true if this constant pool contains no constants.
bool isEmpty() const { return Constants.empty(); }

View File

@ -15,7 +15,6 @@
#ifndef LLVM_CODEGEN_SELECTIONDAG_H
#define LLVM_CODEGEN_SELECTIONDAG_H
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/SelectionDAGCSEMap.h"
#include "llvm/ADT/ilist"
@ -30,6 +29,7 @@ namespace llvm {
class TargetMachine;
class MachineDebugInfo;
class MachineFunction;
class MachineConstantPoolValue;
/// SelectionDAG class - This is used to represent a portion of an LLVM function
/// in a low-level Data Dependence DAG representation suitable for instruction
@ -167,6 +167,13 @@ public:
unsigned Align = 0, int Offset = 0) {
return getConstantPool(C, VT, Align, Offset, true);
}
SDOperand getConstantPool(MachineConstantPoolValue *C, MVT::ValueType VT,
unsigned Align = 0, int Offs = 0, bool isT=false);
SDOperand getTargetConstantPool(MachineConstantPoolValue *C,
MVT::ValueType VT, unsigned Align = 0,
int Offset = 0) {
return getConstantPool(C, VT, Align, Offset, true);
}
SDOperand getBasicBlock(MachineBasicBlock *MBB);
SDOperand getExternalSymbol(const char *Sym, MVT::ValueType VT);
SDOperand getTargetExternalSymbol(const char *Sym, MVT::ValueType VT);

View File

@ -16,6 +16,7 @@
#define LLVM_CODEGEN_SELECTIONDAGCSEMAP_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
namespace llvm {
class SDNode;

View File

@ -19,11 +19,11 @@
#ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H
#define LLVM_CODEGEN_SELECTIONDAGNODES_H
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Value.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/iterator"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/Support/DataTypes.h"
#include <cassert>
@ -32,6 +32,7 @@ namespace llvm {
class SelectionDAG;
class GlobalValue;
class MachineBasicBlock;
class MachineConstantPoolValue;
class SDNode;
template <typename T> struct simplify_type;
template <typename T> struct ilist_traits;
@ -1145,7 +1146,10 @@ public:
};
class ConstantPoolSDNode : public SDNode {
Constant *C;
union {
Constant *ConstVal;
MachineConstantPoolValue *MachineCPVal;
} Val;
int Offset;
unsigned Alignment;
protected:
@ -1153,20 +1157,57 @@ protected:
ConstantPoolSDNode(bool isTarget, Constant *c, MVT::ValueType VT,
int o=0)
: SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
C(c), Offset(o), Alignment(0) {}
Offset(o), Alignment(0) {
assert((int)Offset >= 0 && "Offset is too large");
Val.ConstVal = c;
}
ConstantPoolSDNode(bool isTarget, Constant *c, MVT::ValueType VT, int o,
unsigned Align)
: SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
C(c), Offset(o), Alignment(Align) {}
Offset(o), Alignment(Align) {
assert((int)Offset >= 0 && "Offset is too large");
Val.ConstVal = c;
}
ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v,
MVT::ValueType VT, int o=0)
: SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
Offset(o), Alignment(0) {
assert((int)Offset >= 0 && "Offset is too large");
Val.MachineCPVal = v;
Offset |= 1 << (sizeof(unsigned)*8-1);
}
ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v,
MVT::ValueType VT, int o, unsigned Align)
: SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
Offset(o), Alignment(Align) {
assert((int)Offset >= 0 && "Offset is too large");
Val.MachineCPVal = v;
Offset |= 1 << (sizeof(unsigned)*8-1);
}
public:
Constant *get() const { return C; }
bool isMachineConstantPoolEntry() const {
return (int)Offset < 0;
}
Constant *getConstVal() const {
assert(!isMachineConstantPoolEntry() && "Wrong constantpool type");
return Val.ConstVal;
}
MachineConstantPoolValue *getMachineCPVal() const {
assert(isMachineConstantPoolEntry() && "Wrong constantpool type");
return Val.MachineCPVal;
}
int getOffset() const { return Offset; }
// Return the alignment of this constant pool object, which is either 0 (for
// default alignment) or log2 of the desired value.
unsigned getAlignment() const { return Alignment; }
const Type *getType() const;
static bool classof(const ConstantPoolSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::ConstantPool ||

View File

@ -126,10 +126,11 @@ void AsmPrinter::EmitConstantPool(MachineConstantPool *MCP) {
std::vector<std::pair<MachineConstantPoolEntry,unsigned> > EightByteCPs;
std::vector<std::pair<MachineConstantPoolEntry,unsigned> > SixteenByteCPs;
std::vector<std::pair<MachineConstantPoolEntry,unsigned> > OtherCPs;
std::vector<std::pair<MachineConstantPoolEntry,unsigned> > TargetCPs;
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
MachineConstantPoolEntry CPE = CP[i];
const Constant *CV = CPE.Val;
const Type *Ty = CV->getType();
const Type *Ty = CPE.isMachineConstantPoolEntry()
? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType();
if (TAI->getFourByteConstantSection() &&
TM.getTargetData()->getTypeSize(Ty) == 4)
FourByteCPs.push_back(std::make_pair(CPE, i));
@ -160,11 +161,20 @@ void AsmPrinter::EmitConstantPool(unsigned Alignment, const char *Section,
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
<< CP[i].second << ":\t\t\t\t\t" << TAI->getCommentString() << " ";
WriteTypeSymbolic(O, CP[i].first.Val->getType(), 0) << '\n';
EmitGlobalConstant(CP[i].first.Val);
if (CP[i].first.isMachineConstantPoolEntry()) {
WriteTypeSymbolic(O, CP[i].first.Val.MachineCPVal->getType(), 0) << '\n';
printDataDirective(CP[i].first.Val.MachineCPVal->getType());
EmitMachineConstantPoolValue(CP[i].first.Val.MachineCPVal);
} else {
WriteTypeSymbolic(O, CP[i].first.Val.ConstVal->getType(), 0) << '\n';
EmitGlobalConstant(CP[i].first.Val.ConstVal);
}
if (i != e-1) {
const Type *Ty = CP[i].first.isMachineConstantPoolEntry()
? CP[i].first.Val.MachineCPVal->getType()
: CP[i].first.Val.ConstVal->getType();
unsigned EntSize =
TM.getTargetData()->getTypeSize(CP[i].first.Val->getType());
TM.getTargetData()->getTypeSize(Ty);
unsigned ValEnd = CP[i].first.Offset + EntSize;
// Emit inter-object padding for alignment.
EmitZeros(CP[i+1].first.Offset-ValEnd);
@ -580,40 +590,17 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV) {
}
const Type *type = CV->getType();
switch (type->getTypeID()) {
case Type::BoolTyID:
case Type::UByteTyID: case Type::SByteTyID:
O << TAI->getData8bitsDirective();
break;
case Type::UShortTyID: case Type::ShortTyID:
O << TAI->getData16bitsDirective();
break;
case Type::PointerTyID:
if (TD->getPointerSize() == 8) {
assert(TAI->getData64bitsDirective() &&
"Target cannot handle 64-bit pointer exprs!");
O << TAI->getData64bitsDirective();
break;
}
//Fall through for pointer size == int size
case Type::UIntTyID: case Type::IntTyID:
O << TAI->getData32bitsDirective();
break;
case Type::ULongTyID: case Type::LongTyID:
assert(TAI->getData64bitsDirective() &&
"Target cannot handle 64-bit constant exprs!");
O << TAI->getData64bitsDirective();
break;
case Type::FloatTyID: case Type::DoubleTyID:
assert (0 && "Should have already output floating point constant.");
default:
assert (0 && "Can't handle printing this type of thing");
break;
}
printDataDirective(type);
EmitConstantValueOnly(CV);
O << "\n";
}
void
AsmPrinter::EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
// Target doesn't support this yet!
abort();
}
/// printInlineAsm - This method formats and prints the specified machine
/// instruction that is an inline asm.
void AsmPrinter::printInlineAsm(const MachineInstr *MI) const {
@ -829,3 +816,39 @@ void AsmPrinter::printSetLabel(unsigned uid,
O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << uid << '\n';
}
/// printDataDirective - This method prints the asm directive for the
/// specified type.
void AsmPrinter::printDataDirective(const Type *type) {
const TargetData *TD = TM.getTargetData();
switch (type->getTypeID()) {
case Type::BoolTyID:
case Type::UByteTyID: case Type::SByteTyID:
O << TAI->getData8bitsDirective();
break;
case Type::UShortTyID: case Type::ShortTyID:
O << TAI->getData16bitsDirective();
break;
case Type::PointerTyID:
if (TD->getPointerSize() == 8) {
assert(TAI->getData64bitsDirective() &&
"Target cannot handle 64-bit pointer exprs!");
O << TAI->getData64bitsDirective();
break;
}
//Fall through for pointer size == int size
case Type::UIntTyID: case Type::IntTyID:
O << TAI->getData32bitsDirective();
break;
case Type::ULongTyID: case Type::LongTyID:
assert(TAI->getData64bitsDirective() &&
"Target cannot handle 64-bit constant exprs!");
O << TAI->getData64bitsDirective();
break;
case Type::FloatTyID: case Type::DoubleTyID:
assert (0 && "Should have already output floating point constant.");
default:
assert (0 && "Can't handle printing this type of thing");
break;
}
}

View File

@ -351,6 +351,12 @@ void MachineJumpTableInfo::dump() const { print(std::cerr); }
// MachineConstantPool implementation
//===----------------------------------------------------------------------===//
MachineConstantPool::~MachineConstantPool() {
for (unsigned i = 0, e = Constants.size(); i != e; ++i)
if (Constants[i].isMachineConstantPoolEntry())
delete Constants[i].Val.MachineCPVal;
}
/// getConstantPoolIndex - Create a new entry in the constant pool or return
/// an existing one. User must specify an alignment in bytes for the object.
///
@ -364,13 +370,13 @@ unsigned MachineConstantPool::getConstantPoolIndex(Constant *C,
// FIXME, this could be made much more efficient for large constant pools.
unsigned AlignMask = (1 << Alignment)-1;
for (unsigned i = 0, e = Constants.size(); i != e; ++i)
if (Constants[i].Val == C && (Constants[i].Offset & AlignMask) == 0)
if (Constants[i].Val.ConstVal == C && (Constants[i].Offset & AlignMask)== 0)
return i;
unsigned Offset = 0;
if (!Constants.empty()) {
Offset = Constants.back().Offset;
Offset += TD->getTypeSize(Constants.back().Val->getType());
Offset += TD->getTypeSize(Constants.back().Val.ConstVal->getType());
Offset = (Offset+AlignMask)&~AlignMask;
}
@ -378,10 +384,38 @@ unsigned MachineConstantPool::getConstantPoolIndex(Constant *C,
return Constants.size()-1;
}
unsigned MachineConstantPool::getConstantPoolIndex(MachineConstantPoolValue *V,
unsigned Alignment) {
assert(Alignment && "Alignment must be specified!");
if (Alignment > PoolAlignment) PoolAlignment = Alignment;
// Check to see if we already have this constant.
//
// FIXME, this could be made much more efficient for large constant pools.
unsigned AlignMask = (1 << Alignment)-1;
int Idx = V->getExistingMachineCPValue(this, Alignment);
if (Idx != -1)
return (unsigned)Idx;
unsigned Offset = 0;
if (!Constants.empty()) {
Offset = Constants.back().Offset;
Offset += TD->getTypeSize(Constants.back().Val.MachineCPVal->getType());
Offset = (Offset+AlignMask)&~AlignMask;
}
Constants.push_back(MachineConstantPoolEntry(V, Offset));
return Constants.size()-1;
}
void MachineConstantPool::print(std::ostream &OS) const {
for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
OS << " <cp #" << i << "> is" << *(Value*)Constants[i].Val;
OS << " <cp #" << i << "> is";
if (Constants[i].isMachineConstantPoolEntry())
Constants[i].Val.MachineCPVal->print(OS);
else
OS << *(Value*)Constants[i].Val.ConstVal;
OS << " , offset=" << Constants[i].Offset;
OS << "\n";
}

View File

@ -324,22 +324,26 @@ void ScheduleDAG::AddOperand(MachineInstr *MI, SDOperand Op,
dyn_cast<ConstantPoolSDNode>(Op)) {
int Offset = CP->getOffset();
unsigned Align = CP->getAlignment();
const Type *Type = CP->getType();
// MachineConstantPool wants an explicit alignment.
if (Align == 0) {
if (CP->get()->getType() == Type::DoubleTy)
if (Type == Type::DoubleTy)
Align = 3; // always 8-byte align doubles.
else {
Align = TM.getTargetData()
->getTypeAlignmentShift(CP->get()->getType());
Align = TM.getTargetData()->getTypeAlignmentShift(Type);
if (Align == 0) {
// Alignment of packed types. FIXME!
Align = TM.getTargetData()->getTypeSize(CP->get()->getType());
Align = TM.getTargetData()->getTypeSize(Type);
Align = Log2_64(Align);
}
}
}
unsigned Idx = ConstPool->getConstantPoolIndex(CP->get(), Align);
unsigned Idx;
if (CP->isMachineConstantPoolEntry())
Idx = ConstPool->getConstantPoolIndex(CP->getMachineCPVal(), Align);
else
Idx = ConstPool->getConstantPoolIndex(CP->getConstVal(), Align);
MI->addConstantPoolIndexOperand(Idx, Offset);
} else if (ExternalSymbolSDNode *ES =
dyn_cast<ExternalSymbolSDNode>(Op)) {

View File

@ -17,6 +17,7 @@
#include "llvm/Intrinsics.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetLowering.h"
@ -587,6 +588,25 @@ SDOperand SelectionDAG::getConstantPool(Constant *C, MVT::ValueType VT,
}
SDOperand SelectionDAG::getConstantPool(MachineConstantPoolValue *C,
MVT::ValueType VT,
unsigned Alignment, int Offset,
bool isTarget) {
unsigned Opc = isTarget ? ISD::TargetConstantPool : ISD::ConstantPool;
SelectionDAGCSEMap::NodeID ID(Opc, getVTList(VT));
ID.AddInteger(Alignment);
ID.AddInteger(Offset);
C->AddSelectionDAGCSEId(&ID);
void *IP = 0;
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
return SDOperand(E, 0);
SDNode *N = new ConstantPoolSDNode(isTarget, C, VT, Offset, Alignment);
CSEMap.InsertNode(N, IP);
AllNodes.push_back(N);
return SDOperand(N, 0);
}
SDOperand SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) {
SelectionDAGCSEMap::NodeID ID(ISD::BasicBlock, getVTList(MVT::Other));
ID.AddPointer(MBB);
@ -2586,7 +2606,10 @@ void SDNode::dump(const SelectionDAG *G) const {
std::cerr << "<" << FIDN->getIndex() << ">";
} else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(this)){
int offset = CP->getOffset();
std::cerr << "<" << *CP->get() << ">";
if (CP->isMachineConstantPoolEntry())
std::cerr << "<" << *CP->getMachineCPVal() << ">";
else
std::cerr << "<" << *CP->getConstVal() << ">";
if (offset > 0)
std::cerr << " + " << offset;
else
@ -2648,3 +2671,8 @@ void SelectionDAG::dump() const {
std::cerr << "\n\n";
}
const Type *ConstantPoolSDNode::getType() const {
if (isMachineConstantPoolEntry())
return Val.MachineCPVal->getType();
return Val.ConstVal->getType();
}

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/Support/MathExtras.h"
using namespace llvm;
@ -70,7 +71,11 @@ SelectionDAGCSEMap::NodeID::NodeID(SDNode *N) {
case ISD::TargetConstantPool:
AddInteger(cast<ConstantPoolSDNode>(N)->getAlignment());
AddInteger(cast<ConstantPoolSDNode>(N)->getOffset());
AddPointer(cast<ConstantPoolSDNode>(N)->get());
if (cast<ConstantPoolSDNode>(N)->isMachineConstantPoolEntry())
cast<ConstantPoolSDNode>(N)->getMachineCPVal()->
AddSelectionDAGCSEId(this);
else
AddPointer(cast<ConstantPoolSDNode>(N)->getConstVal());
break;
}
}

View File

@ -15,6 +15,7 @@
#include "llvm/Function.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetMachine.h"
@ -80,14 +81,20 @@ std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
} else if (const FrameIndexSDNode *FIDN = dyn_cast<FrameIndexSDNode>(Node)) {
Op += " " + itostr(FIDN->getIndex());
} else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Node)){
if (ConstantFP *CFP = dyn_cast<ConstantFP>(CP->get()))
Op += "<" + ftostr(CFP->getValue()) + ">";
else if (ConstantInt *CI = dyn_cast<ConstantInt>(CP->get()))
Op += "<" + utostr(CI->getZExtValue()) + ">";
else {
if (CP->isMachineConstantPoolEntry()) {
std::ostringstream SS;
WriteAsOperand(SS, CP->get(), false);
CP->getMachineCPVal()->print(SS);
Op += "<" + SS.str() + ">";
} else {
if (ConstantFP *CFP = dyn_cast<ConstantFP>(CP->getConstVal()))
Op += "<" + ftostr(CFP->getValue()) + ">";
else if (ConstantInt *CI = dyn_cast<ConstantInt>(CP->getConstVal()))
Op += "<" + utostr(CI->getZExtValue()) + ">";
else {
std::ostringstream SS;
WriteAsOperand(SS, CP->getConstVal(), false);
Op += "<" + SS.str() + ">";
}
}
} else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(Node)) {
Op = "BB: ";