summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorMartin Storsjo <martin@martin.st>2017-10-04 05:12:10 +0000
committerMartin Storsjo <martin@martin.st>2017-10-04 05:12:10 +0000
commite14145dcb0070ba1dc743419c6d3ade07893875d (patch)
tree0de086f62af705c6b4a71d4c8e032caf8e2f4229 /llvm/lib
parent68ea360ed1cd30baa0d11737f7223d2e429262bd (diff)
downloadbcm5719-llvm-e14145dcb0070ba1dc743419c6d3ade07893875d.tar.gz
bcm5719-llvm-e14145dcb0070ba1dc743419c6d3ade07893875d.zip
[X86] Fix using the SJLJ jump table on x86_64
The previous version didn't work if the jump table base address didn't fit in 32 bit, since it was encoded as an immediate offset. And in case the jump table is encoded as 32 bit label differences, we need to load and add them to the table base first. This solves the first half of the issues mentioned in PR34720. Also fix some of the errors pointed out by -verify-machineinstrs, by using GR32_NOSPRegClass. Differential Revision: https://reviews.llvm.org/D38333 llvm-svn: 314876
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp75
1 files changed, 65 insertions, 10 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index b02cb8b2f17..a6cd747999c 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -26653,8 +26653,8 @@ X86TargetLowering::EmitSjLjDispatchBlock(MachineInstr &MI,
SetupEntryBlockForSjLj(MI, BB, DispatchBB, FI);
// Create the jump table and associated information
- MachineJumpTableInfo *JTI =
- MF->getOrCreateJumpTableInfo(getJumpTableEncoding());
+ unsigned JTE = getJumpTableEncoding();
+ MachineJumpTableInfo *JTI = MF->getOrCreateJumpTableInfo(JTE);
unsigned MJTI = JTI->createJumpTableIndex(LPadList);
const X86RegisterInfo &RI = TII->getRegisterInfo();
@@ -26677,7 +26677,8 @@ X86TargetLowering::EmitSjLjDispatchBlock(MachineInstr &MI,
.addRegMask(RI.getNoPreservedMask());
}
- unsigned IReg = MRI->createVirtualRegister(&X86::GR32RegClass);
+ // IReg is used as an index in a memory operand and therefore can't be SP
+ unsigned IReg = MRI->createVirtualRegister(&X86::GR32_NOSPRegClass);
addFrameReference(BuildMI(DispatchBB, DL, TII->get(X86::MOV32rm), IReg), FI,
Subtarget.is64Bit() ? 8 : 4);
BuildMI(DispatchBB, DL, TII->get(X86::CMP32ri))
@@ -26685,13 +26686,67 @@ X86TargetLowering::EmitSjLjDispatchBlock(MachineInstr &MI,
.addImm(LPadList.size());
BuildMI(DispatchBB, DL, TII->get(X86::JAE_1)).addMBB(TrapBB);
- BuildMI(DispContBB, DL,
- TII->get(Subtarget.is64Bit() ? X86::JMP64m : X86::JMP32m))
- .addReg(0)
- .addImm(Subtarget.is64Bit() ? 8 : 4)
- .addReg(IReg)
- .addJumpTableIndex(MJTI)
- .addReg(0);
+ if (Subtarget.is64Bit()) {
+ unsigned BReg = MRI->createVirtualRegister(&X86::GR64RegClass);
+ unsigned IReg64 = MRI->createVirtualRegister(&X86::GR64_NOSPRegClass);
+
+ // leaq .LJTI0_0(%rip), BReg
+ BuildMI(DispContBB, DL, TII->get(X86::LEA64r), BReg)
+ .addReg(X86::RIP)
+ .addImm(1)
+ .addReg(0)
+ .addJumpTableIndex(MJTI)
+ .addReg(0);
+ // movzx IReg64, IReg
+ BuildMI(DispContBB, DL, TII->get(TargetOpcode::SUBREG_TO_REG), IReg64)
+ .addImm(0)
+ .addReg(IReg)
+ .addImm(X86::sub_32bit);
+
+ switch (JTE) {
+ case MachineJumpTableInfo::EK_BlockAddress:
+ // jmpq *(BReg,IReg64,8)
+ BuildMI(DispContBB, DL, TII->get(X86::JMP64m))
+ .addReg(BReg)
+ .addImm(8)
+ .addReg(IReg64)
+ .addImm(0)
+ .addReg(0);
+ break;
+ case MachineJumpTableInfo::EK_LabelDifference32: {
+ unsigned OReg = MRI->createVirtualRegister(&X86::GR32RegClass);
+ unsigned OReg64 = MRI->createVirtualRegister(&X86::GR64RegClass);
+ unsigned TReg = MRI->createVirtualRegister(&X86::GR64RegClass);
+
+ // movl (BReg,IReg64,4), OReg
+ BuildMI(DispContBB, DL, TII->get(X86::MOV32rm), OReg)
+ .addReg(BReg)
+ .addImm(4)
+ .addReg(IReg64)
+ .addImm(0)
+ .addReg(0);
+ // movsx OReg64, OReg
+ BuildMI(DispContBB, DL, TII->get(X86::MOVSX64rr32), OReg64).addReg(OReg);
+ // addq BReg, OReg64, TReg
+ BuildMI(DispContBB, DL, TII->get(X86::ADD64rr), TReg)
+ .addReg(OReg64)
+ .addReg(BReg);
+ // jmpq *TReg
+ BuildMI(DispContBB, DL, TII->get(X86::JMP64r)).addReg(TReg);
+ break;
+ }
+ default:
+ llvm_unreachable("Unexpected jump table encoding");
+ }
+ } else {
+ // jmpl *.LJTI0_0(,IReg,4)
+ BuildMI(DispContBB, DL, TII->get(X86::JMP32m))
+ .addReg(0)
+ .addImm(4)
+ .addReg(IReg)
+ .addJumpTableIndex(MJTI)
+ .addReg(0);
+ }
// Add the jump table entries as successors to the MBB.
SmallPtrSet<MachineBasicBlock *, 8> SeenMBBs;
OpenPOWER on IntegriCloud