[PATCH] D148016: CodeGenPrep: insert return after tail calls that return their arg.

Tim Northover via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 11 07:16:32 PDT 2023


t.p.northover created this revision.
Herald added subscribers: hiraditya, mcrosier.
Herald added a project: All.
t.p.northover requested review of this revision.
Herald added a project: LLVM.

When a call returns one of its arguments this is considered a cast by `stripPointerCasts`. So IR returning that directly from a tail call (which should be fine) can become muddied and seem to return an argument from earlier in the function.

This adds some simple checks to spot this situation and reclassify it as the original "tail call -> phi -> return" dataflow.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D148016

Files:
  llvm/lib/CodeGen/CodeGenPrepare.cpp
  llvm/test/CodeGen/AArch64/tailcall-returned.ll


Index: llvm/test/CodeGen/AArch64/tailcall-returned.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/AArch64/tailcall-returned.ll
@@ -0,0 +1,61 @@
+; RUN: opt --codegenprepare -mtriple=arm64-apple-macosx %s -S -o - | FileCheck %s
+
+define ptr @test_already_opt(ptr %in, i1 %tst) {
+; CHECK-LABEL: @test_already_opt
+  br i1 %tst, label %true, label %false
+
+true:
+; CHECK: tail call ptr @return_input(ptr %in)
+; CHECK-NEXT: ret ptr %in
+
+  %call = tail call ptr @return_input(ptr %in)
+  br label %done
+
+false:
+  br label %done
+
+done:
+  %res = phi ptr [ %in, %true ],  [ null, %false ]
+  ret ptr %res
+}
+
+define ptr @test_simple(ptr %in, i1 %tst) {
+; CHECK-LABEL: @test_simple
+  br i1 %tst, label %true, label %false
+
+true:
+; CHECK: tail call ptr @return_input(ptr %in)
+; CHECK-NEXT: ret ptr %call
+
+  %call = tail call ptr @return_input(ptr %in)
+  br label %done
+
+false:
+  br label %done
+
+done:
+  %res = phi ptr [ %call, %true ],  [ null, %false ]
+  ret ptr %res
+}
+
+define ptr @test_unsafe(ptr %in, i1 %tst) {
+; CHECK-LABEL: @test_unsafe
+  br i1 %tst, label %true, label %false
+
+true:
+; CHECK: tail call ptr @return_rando(ptr %in)
+; CHECK-NEXT: br label %done
+
+  %call = tail call ptr @return_rando(ptr %in)
+  br label %done
+
+false:
+  br label %done
+
+done:
+  %res = phi ptr [ %in, %true ],  [ null, %false ]
+  ret ptr %res
+}
+
+declare ptr @return_input(ptr returned)
+declare ptr @return_rando(ptr)
Index: llvm/lib/CodeGen/CodeGenPrepare.cpp
===================================================================
--- llvm/lib/CodeGen/CodeGenPrepare.cpp
+++ llvm/lib/CodeGen/CodeGenPrepare.cpp
@@ -2485,8 +2485,24 @@
       Value *IncomingVal = PN->getIncomingValue(I)->stripPointerCasts();
       CallInst *CI = dyn_cast<CallInst>(IncomingVal);
       BasicBlock *PredBB = PN->getIncomingBlock(I);
+
+      // LLVM treats calls that return one of their arguments as casts, and
+      // forwardoring/looking through that may split a tail call from the value
+      // it returns even more than a phi. Attempt to undo this by looking for a
+      // suitable call in the phi's predecessor block.
+      if (!CI) {
+        BranchInst *BI = dyn_cast<BranchInst>(PredBB->getTerminator());
+        if (!BI || !BI->isUnconditional())
+          continue;
+        CallInst *CastCI =
+            dyn_cast_or_null<CallInst>(BI->getPrevNonDebugInstruction());
+        if (!CastCI || CastCI->getReturnedArgOperand() != IncomingVal)
+          continue;
+        CI = CastCI;
+      }
+
       // Make sure the phi value is indeed produced by the tail call.
-      if (CI && CI->hasOneUse() && CI->getParent() == PredBB &&
+      if (CI && CI->getParent() == PredBB &&
           TLI->mayBeEmittedAsTailCall(CI) &&
           attributesPermitTailCall(F, CI, RetI, *TLI))
         TailCallBBs.push_back(PredBB);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D148016.512442.patch
Type: text/x-patch
Size: 2909 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230411/9e9b1337/attachment.bin>


More information about the llvm-commits mailing list