[LLVMdev] patch for llc/ARM: added mechanism to move switch tables from .text -> .data; also cleanup and documentation

robert muth robert at muth.org
Wed Jun 24 14:20:57 PDT 2009


Evan:

Sorry for the late follow up, I was out of town last week.
Enclosed please find the updated patch including all
your suggestions and a dejagnus test.

Robert

On Thu, Jun 11, 2009 at 2:27 PM, Evan Cheng <evan.cheng at apple.com> wrote:

>
> On Jun 8, 2009, at 2:42 PM, robert muth wrote:
>
> > On Sun, Jun 7, 2009 at 11:53 PM, Evan Cheng <evan.cheng at apple.com>
> > wrote:
> >>
> >> On Jun 7, 2009, at 6:59 AM, robert muth wrote:
> >>
> >>> On Sat, Jun 6, 2009 at 4:51 PM, Evan Cheng<evan.cheng at apple.com>
> >>> wrote:
> >>>> +cl::opt<std::string> FlagJumpTableSection("jumptable-section",
> >>>> +
> >>>> cl::init(".data.jtab"));
> >>>> +
> >>>
> >>> I thought it would be nice to group all the jumptables together.
> >>> But as long as it stays configurable, I am fine to change the
> >>> default
> >>> to ".data".
> >>
> >> There is already a TargetAsmInfo::JumpTableDataSection. Why not just
> >> use that?
> >
> > Nice find. I will use that and possible change the current setting,
> > ".const", if it does not work,
> >
> >>>
> >>>> Is this necessary? Why not just put it in the normal data section?
> >>>> Also "outline" jumptable seems like a strange term. Can you think
> >>>> of
> >>>> something else?
> >>>
> >>>
> >>> Yes, that is a tough one. How about "NonInline" instead.
> >>
> >> Or "OutOfLine"?
> >
> > That works for me.
> >
> >> Please add a test case as well. Thanks,
> >
> > I am not sure how to go about testing.
>
> For this please just add a test case to the llvm dejagnu tests.
>
> thanks,
>
> Evan
>
> >
> > I have  a script that compiles a bunch of test
> > programs (gnu c torture test, etc.) and then runs the executables
> > on qemu.  I run this script with and without my flags and
> > make sure that I do not introduce any new problems
> > -- there are currently plenty of vararg issues.
> >
> > I was thinking of sending this script to the list
> > or maybe checking it into the llvm tree.
> >
> > The key is that whatever tests there are they should just
> > be run with and without the new flag.
> > How do you run backend tests?
> >
> > Robert
> >
> >
> >
> >
> >> Evan
> >>
> >>>
> >>> Robert
> >>>
> >>>> Thanks,
> >>>> Evan
> >>>>
> >>>> Sent from my iPhone
> >>>> On Jun 2, 2009, at 6:26 PM, robert muth <robert at muth.org> wrote:
> >>>>
> >>>> Hi:
> >>>>
> >>>> This is my first patch submission. Hopefully, this is the proper
> >>>> the
> >>>> protocol.
> >>>> Attached is a patch for the llc ARM backend:
> >>>>
> >>>> Added mechanism to generate switch table in a data section
> >>>> rather than having it interleaved with the code.
> >>>> This is controlled by command line flags and off by default.
> >>>> Also, tried to document and improve the code where I modified it.
> >>>>
> >>>> Robert
> >>>>
> >>>> <llc.patch.txt>
> >>>>
> >>>> _______________________________________________
> >>>> LLVM Developers mailing list
> >>>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> >>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
> >>>>
> >>>> _______________________________________________
> >>>> LLVM Developers mailing list
> >>>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> >>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
> >>>>
> >>>>
> >>>
> >>> _______________________________________________
> >>> LLVM Developers mailing list
> >>> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> >>> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
> >>
> >> _______________________________________________
> >> LLVM Developers mailing list
> >> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> >> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
> >>
> >
> > _______________________________________________
> > LLVM Developers mailing list
> > LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20090624/01802d9c/attachment.html>
-------------- next part --------------
Index: test/CodeGen/ARM/switch.ll
===================================================================
--- test/CodeGen/ARM/switch.ll	(revision 0)
+++ test/CodeGen/ARM/switch.ll	(revision 0)
@@ -0,0 +1,82 @@
+; Note: jump table has 7 entries
+; RUN: llvm-as < %s | llc -march=arm  | \
+; RUN:   grep .long | count 7
+; Note: no section change
+; RUN: llvm-as < %s | llc -march=arm  | \
+; RUN:   grep .text | count 1
+; Note: no data section
+; RUN: llvm-as < %s | llc -march=arm  | \
+; RUN:   not grep .data
+;
+; Note: jump table has 7 entries + 1 entry for the table start
+; RUN: llvm-as < %s | llc -march=arm  -outline-jumptables | \
+; RUN:   grep .long | count 8
+; Note one section change
+; RUN: llvm-as < %s | llc -march=arm  -outline-jumptables | \
+; RUN:   grep .text | count 2
+; Note: has data section
+; RUN: llvm-as < %s | llc -march=arm  -outline-jumptables | \
+; RUN:   grep .data | count 1
+
+
+define i32 @f(i32 %i) nounwind {
+entry:
+	%i_addr = alloca i32		; <i32*> [#uses=2]
+	%retval = alloca i32		; <i32*> [#uses=2]
+	%0 = alloca i32		; <i32*> [#uses=8]
+	%"alloca point" = bitcast i32 0 to i32		; <i32> [#uses=0]
+	store i32 %i, i32* %i_addr
+	%1 = load i32* %i_addr, align 4		; <i32> [#uses=1]
+	switch i32 %1, label %bb7 [
+		i32 -2, label %bb
+		i32 -1, label %bb1
+		i32 0, label %bb2
+		i32 1, label %bb3
+		i32 2, label %bb4
+		i32 3, label %bb5
+		i32 4, label %bb6
+	]
+
+bb:		; preds = %entry
+	store i32 33, i32* %0, align 4
+	br label %bb8
+
+bb1:		; preds = %entry
+	store i32 0, i32* %0, align 4
+	br label %bb8
+
+bb2:		; preds = %entry
+	store i32 7, i32* %0, align 4
+	br label %bb8
+
+bb3:		; preds = %entry
+	store i32 4, i32* %0, align 4
+	br label %bb8
+
+bb4:		; preds = %entry
+	store i32 3, i32* %0, align 4
+	br label %bb8
+
+bb5:		; preds = %entry
+	store i32 15, i32* %0, align 4
+	br label %bb8
+
+bb6:		; preds = %entry
+	store i32 9, i32* %0, align 4
+	br label %bb8
+
+bb7:		; preds = %entry
+	store i32 999, i32* %0, align 4
+	br label %bb8
+
+bb8:		; preds = %bb6, %bb5, %bb4, %bb3, %bb2, %bb1, %bb
+	%2 = load i32* %0, align 4		; <i32> [#uses=1]
+	store i32 %2, i32* %retval, align 4
+	br label %return
+
+return:		; preds = %bb8
+	%retval9 = load i32* %retval		; <i32> [#uses=1]
+	ret i32 %retval9
+}
+
+
Index: lib/Target/ARM/ARMISelLowering.h
===================================================================
--- lib/Target/ARM/ARMISelLowering.h	(revision 74072)
+++ lib/Target/ARM/ARMISelLowering.h	(working copy)
@@ -202,9 +202,10 @@
     /// make the right decision when generating code for different targets.
     const ARMSubtarget *Subtarget;
 
-    /// ARMPCLabelIndex - Keep track the number of ARM PC labels created.
-    ///
+    /// ARMPCLabelIndex - Keep track of the number of ARM PC labels created.
     unsigned ARMPCLabelIndex;
+    /// ARMJumpTableIndex - Keep track of the number ofJump Tables
+    unsigned ARMJumpTableIndex;
 
     void addTypeForNEON(MVT VT, MVT PromotedLdStVT, MVT PromotedBitwiseVT);
     void addDRTypeForNEON(MVT VT);
Index: lib/Target/ARM/ARMConstantPoolValue.h
===================================================================
--- lib/Target/ARM/ARMConstantPoolValue.h	(revision 74072)
+++ lib/Target/ARM/ARMConstantPoolValue.h	(working copy)
@@ -25,6 +25,7 @@
   enum ARMCPKind {
     CPValue,
     CPNonLazyPtr,
+    CPDataSegmentJumpTable,
     CPStub
   };
 }
@@ -54,7 +55,6 @@
   ARMConstantPoolValue(GlobalValue *GV, ARMCP::ARMCPKind Kind,
                        const char *Modifier);
 
-
   GlobalValue *getGV() const { return GV; }
   const char *getSymbol() const { return S; }
   const char *getModifier() const { return Modifier; }
@@ -63,6 +63,9 @@
   unsigned getLabelId() const { return LabelId; }
   bool isNonLazyPointer() const { return Kind == ARMCP::CPNonLazyPtr; }
   bool isStub() const { return Kind == ARMCP::CPStub; }
+  bool isValue() const { return Kind == ARMCP::CPValue; }
+  bool isDataSegmentJumpTable() const {
+    return Kind == ARMCP::CPDataSegmentJumpTable; }
   unsigned char getPCAdjustment() const { return PCAdjust; }
 
   virtual int getExistingMachineCPValue(MachineConstantPool *CP,
Index: lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
===================================================================
--- lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp	(revision 74072)
+++ lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp	(working copy)
@@ -33,13 +33,17 @@
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSet.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Mangler.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cctype>
+#include <sstream>
 using namespace llvm;
 
+extern cl::opt<bool> FlagOutlineJumpTables;
+
 STATISTIC(EmittedInsts, "Number of machine instrs printed");
 
 namespace {
@@ -141,6 +145,7 @@
     /// EmitMachineConstantPoolValue - Print a machine constantpool value to
     /// the .s file.
     virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
+      // NOTE: A lot of this code is replicated in  ARMConstantPoolValue::print
       printDataDirective(MCPV->getType());
 
       ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
@@ -157,8 +162,13 @@
       } else if (ACPV->isStub()) {
         FnStubs.insert(Name);
         printSuffixedName(Name, "$stub");
-      } else
+      } else if (ACPV->isDataSegmentJumpTable()) {
+        // requires synchronization with code (grep for "$jumptable$")
+        O << Name << "$jumptable$" << ACPV->getLabelId();
+      } else {
+        assert(ACPV->isValue() && "unknown CP kind");
         O << Name;
+      }
       if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
       if (ACPV->getPCAdjustment() != 0) {
         O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
@@ -757,12 +767,31 @@
   }
 }
 
+
 void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) {
-  const MachineOperand &MO1 = MI->getOperand(OpNo);
-  const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id
-  unsigned JTI = MO1.getIndex();
-  O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
-    << '_' << JTI << '_' << MO2.getImm() << ":\n";
+  std::stringstream  prefix;
+
+  const unsigned JTI =  MI->getOperand(OpNo).getIndex();
+  const unsigned uid = MI->getOperand(OpNo+1).getImm();
+
+  if (FlagOutlineJumpTables) {
+    // needs to be synchronized with ARMConstantPoolValue.cpp
+    prefix << ".T$jumptable$" << uid;
+  } else {
+    // needs to be synchronized with other places in this file
+    prefix  << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
+            << '_' << JTI << '_' << uid;
+  }
+
+  if (FlagOutlineJumpTables) {
+    // switch out of text section
+    O << TAI->getJumpTableDataSection();
+    O << ".align 4\n";
+    O << "\n\n";
+  }
+
+  // the table label
+  O << prefix.str() << ":\n";
 
   const char *JTEntryDirective = TAI->getJumpTableDirective();
   if (!JTEntryDirective)
@@ -777,24 +806,28 @@
   for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
     MachineBasicBlock *MBB = JTBBs[i];
     if (UseSet && JTSets.insert(MBB).second)
-      printPICJumpTableSetLabel(JTI, MO2.getImm(), MBB);
+      printPICJumpTableSetLabel(JTI, uid, MBB);
 
     O << JTEntryDirective << ' ';
     if (UseSet)
-      O << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
-        << '_' << JTI << '_' << MO2.getImm()
-        << "_set_" << MBB->getNumber();
+      O << prefix.str() << "_set_" << MBB->getNumber();
     else if (TM.getRelocationModel() == Reloc::PIC_) {
       printBasicBlockLabel(MBB, false, false, false);
       // If the arch uses custom Jump Table directives, don't calc relative to JT
       if (!TAI->getJumpTableDirective()) 
-        O << '-' << TAI->getPrivateGlobalPrefix() << "JTI"
-          << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm();
+        O << '-' << prefix.str();
     } else
       printBasicBlockLabel(MBB, false, false, false);
     if (i != e-1)
       O << '\n';
   }
+
+  if (FlagOutlineJumpTables) {
+    // switch back into the text section
+    O << "\n\n";
+    O << ".text\n";
+    O << "\n\n";
+  }
 }
 
 
Index: lib/Target/ARM/ARMTargetAsmInfo.cpp
===================================================================
--- lib/Target/ARM/ARMTargetAsmInfo.cpp	(revision 74072)
+++ lib/Target/ARM/ARMTargetAsmInfo.cpp	(working copy)
@@ -52,6 +52,7 @@
   SetDirective = "\t.set\t";
   ProtectedDirective = NULL;
   HasDotTypeDotSizeDirective = false;
+  JumpTableDataSection = "\t.section .data,\"aMS\",%progbits,1\n";
   SupportsDebugInformation = true;
 }
 
@@ -86,6 +87,7 @@
     StaticCtorsSection = "\t.section .ctors,\"aw\",%progbits";
     StaticDtorsSection = "\t.section .dtors,\"aw\",%progbits";
   }
+  JumpTableDataSection = "\t.section .data,\"aMS\",%progbits,1\n";
   SupportsDebugInformation = true;
 }
 
Index: lib/Target/ARM/ARMISelLowering.cpp
===================================================================
--- lib/Target/ARM/ARMISelLowering.cpp	(revision 74072)
+++ lib/Target/ARM/ARMISelLowering.cpp	(working copy)
@@ -36,9 +36,16 @@
 #include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/ADT/VectorExtras.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/MathExtras.h"
+
 using namespace llvm;
 
+
+
+cl::opt<bool> FlagOutlineJumpTables("outline-jumptables",
+                                    cl::desc("move jumptables from text to data"));
+
 static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
                                    CCValAssign::LocInfo &LocInfo,
                                    ISD::ArgFlagsTy &ArgFlags,
@@ -1686,27 +1693,119 @@
   return Res;
 }
 
-SDValue ARMTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) {
+
+
+// Similar to LowerBR_JT_Inline except that the jumptable
+// is moved to the data segment.
+// This causes a extra load to access the table but keeps the
+// text segment small and avoids some issues with generating PIC
+// Needs to be activated with a commandline flag.
+static SDValue LowerBR_JT_OutOfLine(SDValue Op,
+                                  SelectionDAG &DAG,
+                                  unsigned Num,
+                                  MVT PTy) {
+
   SDValue Chain = Op.getOperand(0);
-  SDValue Table = Op.getOperand(1);
-  SDValue Index = Op.getOperand(2);
-  DebugLoc dl = Op.getDebugLoc();
 
-  MVT PTy = getPointerTy();
-  JumpTableSDNode *JT = cast<JumpTableSDNode>(Table);
+  const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op.getOperand(1));
+  const SDValue Index = Op.getOperand(2);
+
+
+  const DebugLoc dl = Op.getDebugLoc();
+
+  const SDValue UId =  DAG.getConstant(Num, PTy);
+  const SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PTy);
+
+  // create a new global symbol for the jumptable
+  ARMConstantPoolValue *CPV = new ARMConstantPoolValue(".T", Num,
+                                          ARMCP::CPDataSegmentJumpTable);
+  const SDValue CPAddr = DAG.getTargetConstantPool(CPV, PTy, 4);
+
+  // An ARM idiosyncrasy: wrap each constant pool entry before accessing it
+  const SDValue Wrapper = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr);
+
+  // Load Table start from constan pool
+  const SDValue Table = DAG.getLoad(PTy, dl, DAG.getEntryNode(), Wrapper, NULL, 0);
+
+  // table entries are 4 bytes, so multiple index by 4
+  const SDValue ScaledIndex = DAG.getNode(ISD::MUL, dl, PTy, Index, DAG.getConstant(4, PTy));
+
+  // add scaled index to table beginning
+  const SDValue TabEntryAddr = DAG.getNode(ISD::ADD, dl, PTy, ScaledIndex, Table);
+  const SDValue JumpTarget = DAG.getLoad(PTy, dl, Chain, TabEntryAddr, NULL, 0);
+
+  return DAG.getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, JumpTarget, JTI, UId);
+}
+
+
+static SDValue LowerBR_JT_Inline(SDValue Op,
+                                 SelectionDAG &DAG,
+                                 bool isPIC,
+                                 MVT PTy) {
+  //  The Jumptable idiom we are aiming for looks somthing like this:
+  //
+  //          .set PCRELV0, (.LJTI9_0_0-(.LPCRELL0+8))
+  //  .LPCRELL0:
+  //          add r3, pc, #PCRELV0
+  //          ldr pc, [r3, +r0, lsl #2]
+  //  .LJTI9_0_0:
+  //          .long    .LBB9_2
+  //          .long    .LBB9_5
+  //          .long    .LBB9_7
+  //          .long    .LBB9_4
+  //          .long    .LBB9_8
+  //
+  // In pic mode the table entries are relative to table beginning
+  // requiring and extra addition
+  //
+  // The code generation logic for ARMISD::BR_JT will also
+  // emit the table (c.f. ARMAsmPrinter::printJTBlockOperand())
+  // Also check  "def BR_JTm" in ARMInstrInfo.td
+
+  // allocate constant pool entry
   ARMFunctionInfo *AFI = DAG.getMachineFunction().getInfo<ARMFunctionInfo>();
-  SDValue UId =  DAG.getConstant(AFI->createJumpTableUId(), PTy);
-  SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PTy);
-  Table = DAG.getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI, UId);
-  Index = DAG.getNode(ISD::MUL, dl, PTy, Index, DAG.getConstant(4, PTy));
-  SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table);
-  bool isPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_;
-  Addr = DAG.getLoad(isPIC ? (MVT)MVT::i32 : PTy, dl,
-                     Chain, Addr, NULL, 0);
-  Chain = Addr.getValue(1);
-  if (isPIC)
-    Addr = DAG.getNode(ISD::ADD, dl, PTy, Addr, Table);
-  return DAG.getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI, UId);
+
+  SDValue Chain = Op.getOperand(0);
+
+  const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op.getOperand(1));
+  const SDValue Index = Op.getOperand(2);
+  const DebugLoc dl = Op.getDebugLoc();
+
+
+  const SDValue UId =  DAG.getConstant(AFI->createJumpTableUId(), PTy);
+
+  const SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PTy);
+
+  // this uses pcrel magic to materialize the table start address
+  const SDValue Table = DAG.getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI, UId);
+
+  // table entries are 4 bytes, so multiple index by 4
+   const SDValue ScaledIndex = DAG.getNode(ISD::MUL, dl, PTy, Index, DAG.getConstant(4, PTy));
+
+  // add scaled index to table beginning
+  const SDValue TabEntryAddr = DAG.getNode(ISD::ADD, dl, PTy, ScaledIndex, Table);
+  SDValue JumpTarget;
+  if (isPIC) {
+     JumpTarget = DAG.getLoad((MVT)MVT::i32, dl, Chain, TabEntryAddr, NULL, 0);
+     Chain = JumpTarget.getValue(1);
+     // the table entry is not the actual target but relative to other stuff
+     // TODO: explain the exact magic here
+     JumpTarget = DAG.getNode(ISD::ADD, dl, PTy, JumpTarget, Table);
+  } else {
+    JumpTarget = DAG.getLoad(PTy, dl, Chain, TabEntryAddr, NULL, 0);
+    Chain = JumpTarget.getValue(1);
+  }
+
+  return DAG.getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, JumpTarget, JTI, UId);
+}
+
+SDValue ARMTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) {
+  if (FlagOutlineJumpTables) {
+    return LowerBR_JT_OutOfLine(Op, DAG, ++ARMJumpTableIndex, getPointerTy());
+  } else {
+    const bool isPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_;
+    return LowerBR_JT_Inline(Op, DAG, isPIC, getPointerTy());
+  }
 }
 
 static SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) {
Index: lib/Target/ARM/ARMConstantPoolValue.cpp
===================================================================
--- lib/Target/ARM/ARMConstantPoolValue.cpp	(revision 74072)
+++ lib/Target/ARM/ARMConstantPoolValue.cpp	(working copy)
@@ -84,12 +84,26 @@
 }
 
 void ARMConstantPoolValue::print(raw_ostream &O) const {
+  // NOTE: this is not used for codegeneration, moreover
+  //       some of the logic is replicated in
+  //       EmitMachineConstantPoolValue()
+
   if (GV)
     O << GV->getName();
   else
     O << S;
-  if (isNonLazyPointer()) O << "$non_lazy_ptr";
-  else if (isStub()) O << "$stub";
+
+  if (isNonLazyPointer()) {
+    O << "$non_lazy_ptr";
+  } else if (isStub()) {
+    O << "$stub";
+  } else if (isDataSegmentJumpTable()) {
+    // requires synchronization with ARMAsmPrinter.cpp
+    O << "$jumptable$" << LabelId;
+  } else {
+    assert(isValue() && "unknown CP kind");
+  }
+
   if (Modifier) O << "(" << Modifier << ")";
   if (PCAdjust != 0) {
     O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust;


More information about the llvm-dev mailing list