Lower @llvm.experimental.deoptimize as a noreturn call
authorSanjoy Das <sanjoy@playingwithpointers.com>
Wed, 6 Apr 2016 01:33:49 +0000 (01:33 +0000)
committerSanjoy Das <sanjoy@playingwithpointers.com>
Wed, 6 Apr 2016 01:33:49 +0000 (01:33 +0000)
While preserving the return value for @llvm.experimental.deoptimize at
the IR level is useful during mid-level optimization, doing so at the
machine instruction level requires generating some extra code and a
return that is non-ideal.  This change has LLVM lower

```
  %val = call @llvm.experimental.deoptimize
  ret %val
```

to effectively

```
  call @__llvm_deoptimize()
  unreachable
```

instead.

llvm-svn: 265502

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
llvm/test/CodeGen/X86/deopt-intrinsic.ll

index 91c0a04..f6b4262 100644 (file)
@@ -1377,6 +1377,18 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
   SmallVector<ISD::OutputArg, 8> Outs;
   SmallVector<SDValue, 8> OutVals;
 
+  // Calls to @llvm.experimental.deoptimize don't generate a return value, so
+  // lower
+  //
+  //   %val = call <ty> @llvm.experimental.deoptimize()
+  //   ret <ty> %val
+  //
+  // differently.
+  if (I.getParent()->getTerminatingDeoptimizeCall()) {
+    LowerDeoptimizingReturn();
+    return;
+  }
+
   if (!FuncInfo.CanLowerReturn) {
     unsigned DemoteReg = FuncInfo.DemoteRegister;
     const Function *F = I.getParent()->getParent();
index 214c510..2d20026 100644 (file)
@@ -779,10 +779,12 @@ public:
                                     const BasicBlock *EHPadBB);
 
   void LowerDeoptimizeCall(const CallInst *CI);
+  void LowerDeoptimizingReturn();
 
   void LowerCallSiteWithDeoptBundleImpl(ImmutableCallSite CS, SDValue Callee,
                                         const BasicBlock *EHPadBB,
-                                        bool VarArgDisallowed);
+                                        bool VarArgDisallowed,
+                                        bool ForceVoidReturnTy);
 
 private:
   // Terminator instructions.
index edec366..f489e3b 100644 (file)
@@ -823,11 +823,13 @@ SelectionDAGBuilder::LowerStatepoint(ImmutableStatepoint ISP,
 
 void SelectionDAGBuilder::LowerCallSiteWithDeoptBundleImpl(
     ImmutableCallSite CS, SDValue Callee, const BasicBlock *EHPadBB,
-    bool VarArgDisallowed) {
+    bool VarArgDisallowed, bool ForceVoidReturnTy) {
   StatepointLoweringInfo SI(DAG);
   unsigned ArgBeginIndex = CS.arg_begin() - CS.getInstruction()->op_begin();
-  populateCallLoweringInfo(SI.CLI, CS, ArgBeginIndex, CS.getNumArgOperands(),
-                           Callee, CS.getType(), false);
+  populateCallLoweringInfo(
+      SI.CLI, CS, ArgBeginIndex, CS.getNumArgOperands(), Callee,
+      ForceVoidReturnTy ? Type::getVoidTy(*DAG.getContext()) : CS.getType(),
+      false);
   if (!VarArgDisallowed)
     SI.CLI.IsVarArg = CS.getFunctionType()->isVarArg();
 
@@ -856,7 +858,8 @@ void SelectionDAGBuilder::LowerCallSiteWithDeoptBundleImpl(
 void SelectionDAGBuilder::LowerCallSiteWithDeoptBundle(
     ImmutableCallSite CS, SDValue Callee, const BasicBlock *EHPadBB) {
   LowerCallSiteWithDeoptBundleImpl(CS, Callee, EHPadBB,
-                                   /* VarArgDisallowed = */ false);
+                                   /* VarArgDisallowed = */ false,
+                                   /* ForceVoidReturnTy  = */ false);
 }
 
 void SelectionDAGBuilder::visitGCResult(const CallInst &CI) {
@@ -941,7 +944,18 @@ void SelectionDAGBuilder::LowerDeoptimizeCall(const CallInst *CI) {
                                          TLI.getPointerTy(DAG.getDataLayout()));
 
   // We don't lower calls to __llvm_deoptimize as varargs, but as a regular
-  // call.
+  // call.  We also do not lower the return value to any virtual register, and
+  // change the immediately following return to a trap instruction.
   LowerCallSiteWithDeoptBundleImpl(CI, Callee, /* EHPadBB = */ nullptr,
-                                   /* VarArgDisallowed = */ true);
+                                   /* VarArgDisallowed = */ true,
+                                   /* ForceVoidReturnTy = */ true);
+}
+
+void SelectionDAGBuilder::LowerDeoptimizingReturn() {
+  // We do not lower the return value from llvm.deoptimize to any virtual
+  // register, and change the immediately following return to a trap
+  // instruction.
+  if (DAG.getTarget().Options.TrapUnreachable)
+    DAG.setRoot(
+        DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, DAG.getRoot()));
 }
index f9d7527..008075b 100644 (file)
@@ -18,8 +18,6 @@ define i32 @caller_0() {
 ; CHECK-NEXT: {{.+cfi.+}}
 ; CHECK-NEXT: callq    ___llvm_deoptimize
 ; CHECK-NEXT: {{Ltmp[0-9]+}}:
-; CHECK-NEXT: popq %rcx
-; CHECK-NEXT: retq
 entry:
   %v = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 0) ]
   ret i32 %v
@@ -36,8 +34,6 @@ define i8 @caller_1() {
 ; CHECK-NEXT: movl     $42, %edi
 ; CHECK-NEXT: callq    ___llvm_deoptimize
 ; CHECK-NEXT: {{Ltmp[0-9]+}}:
-; CHECK-NEXT: popq %rcx
-; CHECK-NEXT: retq
 
 entry:
   %v = call i8(...) @llvm.experimental.deoptimize.i8(i32 42, float 500.0) [ "deopt"(i32 1) ]
@@ -55,8 +51,6 @@ define i64 @caller_2() {
 ; CHECK-NEXT: movl     $42, %eax
 ; CHECK-NEXT: callq    ___llvm_deoptimize
 ; CHECK-NEXT: {{Ltmp[0-9]+}}:
-; CHECK-NEXT: popq %rcx
-; CHECK-NEXT: retq
 
 entry:
   %v = call webkit_jscc i64(...) @llvm.experimental.deoptimize.i64(i32 42, float 500.0) [ "deopt"(i32 3) ]