[PATCH] D75598: [InstCombine] Handle gc.relocate(null) in one iteration

Serguei Katkov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 4 02:52:58 PST 2020


skatkov created this revision.
skatkov added reviewers: reames, dantrushin.
Herald added a subscriber: hiraditya.
Herald added a project: LLVM.
skatkov marked an inline comment as done.
skatkov added inline comments.
skatkov updated this revision to Diff 248132.


================
Comment at: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp:4388
+  // users to worklist if they can be simplified to null.
+  // This is mostly compile time safe. Actually C can be transformed on the next
+  // iteration if InstCombine while we want to handle all gc.relocate chains in
----------------
safe -> save.


InstCombine adds users of transformed instruction to working list to
process on the same iteration. However gc.relocate may have a hidden
user (next gc.relocate) which is connected through gc.statepoint intrinsic.

In this case if the next gc.relocation is already processed it will not be added
to worklist and will not be able to be processed on the same iteration.
Let's we have the following case:
A = gc.relocate(null)
B = statepoint(A)
C = gc.relocate(B, hidden(A))
If C is already considered then after replacement of A with null, statepoint B
instruction will be added to the queue but not C.
C can be processed only on the next iteration.

If the chain of relocation is pretty long the many iteration may be required.
So this change is mostly compiler time optimization.


https://reviews.llvm.org/D75598

Files:
  llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
  llvm/test/Transforms/InstCombine/statepoint-null.ll


Index: llvm/test/Transforms/InstCombine/statepoint-null.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/InstCombine/statepoint-null.ll
@@ -0,0 +1,33 @@
+; RUN: opt < %s -instcombine -instcombine-max-iterations=1 -S | FileCheck %s
+; These tests check the optimizations specific to
+; pointers being relocated at a statepoint.
+
+
+declare void @func()
+
+define i1 @test_null(i1 %cond) gc "statepoint-example" {
+entry:
+  br i1 %cond, label %left, label %right
+
+right:
+  br label %merge
+
+left:
+  %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* null)
+  %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token,  i32 7, i32 7)
+  br label %merge
+
+merge:
+  %pnew_phi = phi i32 addrspace(1)* [null, %right], [%pnew, %left]
+  %safepoint_token2 = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %pnew_phi)
+  %pnew2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2,  i32 7, i32 7)
+  %cmp = icmp eq i32 addrspace(1)* %pnew2, null
+  ret i1 %cmp
+; CHECK-LABEL: test_null
+; CHECK-NOT: %pnew
+; CHECK-NOT: %pnew2
+; CHECK: ret i1 true
+}
+
+declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
+declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) #3
Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -4375,6 +4375,26 @@
 
 /// Improvements for call, callbr and invoke instructions.
 Instruction *InstCombiner::visitCallBase(CallBase &Call) {
+  // Special handling of statepoint intrinsic.
+  // Let's we have the following case:
+  // A = gc.relocate(null)
+  // B = statepoint(A)
+  // C = gc.relocate(A)
+  // A will be substituted with null and its user B will be added to worklist.
+  // Statepoint B is not simplified and if C was considered before it will be
+  // re-considered after simplification of A.
+  // To resolve this case while processing statepoint B we add all gc.relocate
+  // users to worklist if they can be simplified to null.
+  // This is mostly to save compile time. Actually C can be transformed on
+  // the next iteration if InstCombine while we want to handle all gc.relocate
+  // chains in one iteraton.
+  if (isStatepoint(Call))
+    for (User *U : Call.users())
+      if (auto *GCR = dyn_cast<GCRelocateInst>(U))
+        if (isa<PointerType>(U->getType()))
+          if (isa<ConstantPointerNull>(GCR->getDerivedPtr()))
+            Worklist.add(GCR);
+
   if (isAllocationFn(&Call, &TLI))
     annotateAnyAllocSite(Call, &TLI);
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D75598.248132.patch
Type: text/x-patch
Size: 3041 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200304/5c84c230/attachment-0001.bin>


More information about the llvm-commits mailing list