Statepoint: Fix handling of Far Immediate calls
authorSwaroop Sridhar <Swaroop.Sridhar@microsoft.com>
Thu, 4 Jun 2015 23:03:21 +0000 (23:03 +0000)
committerSwaroop Sridhar <Swaroop.Sridhar@microsoft.com>
Thu, 4 Jun 2015 23:03:21 +0000 (23:03 +0000)
gc.statepoint intrinsics with a far immediate call target
were lowered incorrectly as pc-rel32 calls.

This change fixes the problem, and generates an indirect call
via a scratch register.

For example:

Intrinsic:
  %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* inttoptr (i64 140727162896504 to void ()*), i32 0, i32 0, i32 0, i32 0)

Old Incorrect Lowering:
  callq 140727162896504

New Correct Lowering:
  movabsq $140727162896504, %rax
  callq *%rax

In lowerCallFromStatepoint(), the callee-target was modified and
represented as a "TargetConstant" node, rather than a "Constant" node.
Undoing this modification enabled LowerCall() to generate the
correct CALL instruction.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239114 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/StatepointLowering.cpp
test/CodeGen/X86/statepoint-far-call.ll [new file with mode: 0644]

index 2d4ab6c5077a2322a1fcba63f6aa84381322cc47..8bbfa01e7594ca841de2bcb3fdcb0de903691679 100644 (file)
@@ -238,17 +238,6 @@ lowerCallFromStatepoint(ImmutableStatepoint ISP, MachineBasicBlock *LandingPad,
 
   SDValue ActualCallee = Builder.getValue(ISP.getActualCallee());
 
-  // Handle immediate and symbolic callees.
-  if (auto *ConstCallee = dyn_cast<ConstantSDNode>(ActualCallee.getNode()))
-    ActualCallee = Builder.DAG.getIntPtrConstant(ConstCallee->getZExtValue(),
-                                                 Builder.getCurSDLoc(),
-                                                 /*isTarget=*/true);
-  else if (auto *SymbolicCallee =
-               dyn_cast<GlobalAddressSDNode>(ActualCallee.getNode()))
-    ActualCallee = Builder.DAG.getTargetGlobalAddress(
-        SymbolicCallee->getGlobal(), SDLoc(SymbolicCallee),
-        SymbolicCallee->getValueType(0));
-
   assert(CS.getCallingConv() != CallingConv::AnyReg &&
          "anyregcc is not supported on statepoints!");
 
diff --git a/test/CodeGen/X86/statepoint-far-call.ll b/test/CodeGen/X86/statepoint-far-call.ll
new file mode 100644 (file)
index 0000000..cd8dd0f
--- /dev/null
@@ -0,0 +1,22 @@
+; RUN: llc < %s | FileCheck %s\r
+; Test to check that Statepoints with X64 far-immediate targets\r
+; are lowered correctly to an indirect call via a scratch register.\r
+\r
+target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"\r
+target triple = "x86_64-pc-win64"\r
+\r
+define void @test_far_call() gc "statepoint-example" {\r
+; CHECK-LABEL: test_far_call\r
+; CHECK: pushq %rax\r
+; CHECK: movabsq $140727162896504, %rax \r
+; CHECK: callq *%rax\r
+; CHECK: popq %rax\r
+; CHECK: retq\r
+\r
+entry:\r
+  %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* inttoptr (i64 140727162896504 to void ()*), i32 0, i32 0, i32 0, i32 0)\r
+  ret void\r
+}\r
+\r
+declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) \r
+\r