[llvm] r245452 - x32. Fixes jmp %reg in x32

JF Bastien via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 19 09:17:08 PDT 2015


Author: jfb
Date: Wed Aug 19 11:17:08 2015
New Revision: 245452

URL: http://llvm.org/viewvc/llvm-project?rev=245452&view=rev
Log:
x32. Fixes jmp %reg in x32

x32 has 32-bit pointers; x86-64 can't jmp %r32. This patch addresses this issue by explicitly zero-extending brind's target to 64-bits.

Author: jpp

Reviewers: jfb, dschuff, pavel.v.chupin

Subscribers: llvm-commits

Differential revision: http://reviews.llvm.org/D12112

Added:
    llvm/trunk/test/CodeGen/X86/x32-indirectbr.ll
Modified:
    llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp

Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=245452&r1=245451&r2=245452&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Wed Aug 19 11:17:08 2015
@@ -2224,6 +2224,27 @@ SDNode *X86DAGToDAGISel::Select(SDNode *
 
   switch (Opcode) {
   default: break;
+  case ISD::BRIND: {
+    if (Subtarget->isTargetNaCl())
+      // NaCl has its own pass where jmp %r32 are converted to jmp %r64. We
+      // leave the instruction alone.
+      break;
+    if (Subtarget->isTarget64BitILP32()) {
+      // Converts a 32-bit register to a 64-bit, zero-extended version of
+      // it. This is needed because x86-64 can do many things, but jmp %r32
+      // ain't one of them.
+      const SDValue &Target = Node->getOperand(1);
+      assert(Target.getSimpleValueType() == llvm::MVT::i32);
+      SDValue ZextTarget = CurDAG->getZExtOrTrunc(Target, dl, EVT(MVT::i64));
+      SDValue Brind = CurDAG->getNode(ISD::BRIND, dl, MVT::Other,
+                                      Node->getOperand(0), ZextTarget);
+      ReplaceUses(SDValue(Node, 0), Brind);
+      SelectCode(ZextTarget.getNode());
+      SelectCode(Brind.getNode());
+      return nullptr;
+    }
+    break;
+  }
   case ISD::INTRINSIC_W_CHAIN: {
     unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
     switch (IntNo) {

Added: llvm/trunk/test/CodeGen/X86/x32-indirectbr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/x32-indirectbr.ll?rev=245452&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/x32-indirectbr.ll (added)
+++ llvm/trunk/test/CodeGen/X86/x32-indirectbr.ll Wed Aug 19 11:17:08 2015
@@ -0,0 +1,26 @@
+; RUN: llc < %s -mtriple=x86_64-none-none-gnux32 -mcpu=generic | FileCheck %s
+; RUN: llc < %s -mtriple=x86_64-none-none-gnux32 -mcpu=generic -fast-isel | FileCheck %s
+; Bug 22859
+;
+; x32 pointers are 32-bits wide. x86-64 indirect branches use the full 64-bit
+; registers. Therefore, x32 CodeGen needs to zero extend indirectbr's target to
+; 64-bit.
+
+define i8 @test1() nounwind ssp {
+entry:
+  %0 = select i1 undef,                           ; <i8*> [#uses=1]
+              i8* blockaddress(@test1, %bb),
+              i8* blockaddress(@test1, %bb6)
+  indirectbr i8* %0, [label %bb, label %bb6]
+bb:                                               ; preds = %entry
+  ret i8 1
+
+bb6:                                              ; preds = %entry
+  ret i8 2
+}
+; CHECK-LABEL: @test1
+; We are looking for a movl ???, %r32 followed by a 64-bit jmp through the
+; same register.
+; CHECK: movl {{.*}}, %{{e|r}}[[REG:.[^d]*]]{{d?}}
+; CHECK-NEXT: jmpq *%r[[REG]]
+




More information about the llvm-commits mailing list