[GCRelocate] Add a peephole to canonicalize base pointer relocation
authorPhilip Reames <listmail@philipreames.com>
Tue, 24 Sep 2019 17:24:16 +0000 (17:24 +0000)
committerPhilip Reames <listmail@philipreames.com>
Tue, 24 Sep 2019 17:24:16 +0000 (17:24 +0000)
If we generate the gc.relocate, and then later prove two arguments to the statepoint are equivalent, we should canonicalize the gc.relocate to the form we would have produced if this had been known before rewriting.

llvm-svn: 372771

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/test/Transforms/InstCombine/gc.relocate.ll

index 0b4e9e9af3cba237af55efad11d77f5977e28aed..5c0e648f490a08b097e03b3f6508a71d2c84e4bc 100644 (file)
@@ -3951,10 +3951,21 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
     break;
   }
   case Intrinsic::experimental_gc_relocate: {
+    auto &GCR = *cast<GCRelocateInst>(II);
+
+    // If we have two copies of the same pointer in the statepoint argument
+    // list, canonicalize to one.  This may let us common gc.relocates.
+    if (GCR.getBasePtr() == GCR.getDerivedPtr() &&
+        GCR.getBasePtrIndex() != GCR.getDerivedPtrIndex()) {
+      auto *OpIntTy = GCR.getOperand(2)->getType();
+      II->setOperand(2, ConstantInt::get(OpIntTy, GCR.getBasePtrIndex()));
+      return II;
+    }
+    
     // Translate facts known about a pointer before relocating into
     // facts about the relocate value, while being careful to
     // preserve relocation semantics.
-    Value *DerivedPtr = cast<GCRelocateInst>(II)->getDerivedPtr();
+    Value *DerivedPtr = GCR.getDerivedPtr();
 
     // Remove the relocation if unused, note that this check is required
     // to prevent the cases below from looping forever.
index 78b3b5f42f91a6e143de2b9fe74afe7c28384a1f..f8eade6f11f53b4df3467c75f98128d372acaa7d 100644 (file)
@@ -52,6 +52,17 @@ entry:
   ret <2 x i8 addrspace(1)*> %obj.relocated
 }
 
+define i32 addrspace(1)* @canonical_base(i32 addrspace(1)* %dparam) gc "statepoint-example" {
+; Checks that a nonnull pointer
+; CHECK-LABEL: @canonical_base
+; CHECK: (token %tok, i32 7, i32 7) ; (%dparam, %dparam)
+entry:
+  %tok = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam, i32 addrspace(1)* %dparam)
+  %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok,  i32 7, i32 8)
+  ret i32 addrspace(1)* %relocate
+}
+
+
 declare void @do_safepoint()
 
 declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)