[llvm] 029f1a5 - [LazyCallGraph] Skip blockaddresses

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 1 13:10:44 PDT 2021


Author: Arthur Eubanks
Date: 2021-11-01T13:10:24-07:00
New Revision: 029f1a53448979365ab965572356b83edc82f755

URL: https://github.com/llvm/llvm-project/commit/029f1a53448979365ab965572356b83edc82f755
DIFF: https://github.com/llvm/llvm-project/commit/029f1a53448979365ab965572356b83edc82f755.diff

LOG: [LazyCallGraph] Skip blockaddresses

blockaddresses do not participate in the call graph since the only
instructions that use them must all return to someplace within the
current function. And passes cannot retrieve a function address from a
blockaddress.

This was suggested by efriedma in D58260.

Fixes PR50881.

Reviewed By: nickdesaulniers

Differential Revision: https://reviews.llvm.org/D112178

Added: 
    llvm/test/Analysis/LazyCallGraph/blockaddress.ll

Modified: 
    llvm/lib/Analysis/LazyCallGraph.cpp
    llvm/test/Transforms/Attributor/IPConstantProp/dangling-block-address.ll
    llvm/test/Transforms/Attributor/liveness.ll
    llvm/unittests/Analysis/LazyCallGraphTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/LazyCallGraph.cpp b/llvm/lib/Analysis/LazyCallGraph.cpp
index 672a2c6eba582..0007c54b16d07 100644
--- a/llvm/lib/Analysis/LazyCallGraph.cpp
+++ b/llvm/lib/Analysis/LazyCallGraph.cpp
@@ -1973,28 +1973,10 @@ void LazyCallGraph::visitReferences(SmallVectorImpl<Constant *> &Worklist,
       continue;
     }
 
-    // The blockaddress constant expression is a weird special case, we can't
-    // generically walk its operands the way we do for all other constants.
-    if (BlockAddress *BA = dyn_cast<BlockAddress>(C)) {
-      // If we've already visited the function referred to by the block
-      // address, we don't need to revisit it.
-      if (Visited.count(BA->getFunction()))
-        continue;
-
-      // If all of the blockaddress' users are instructions within the
-      // referred to function, we don't need to insert a cycle.
-      if (llvm::all_of(BA->users(), [&](User *U) {
-            if (Instruction *I = dyn_cast<Instruction>(U))
-              return I->getFunction() == BA->getFunction();
-            return false;
-          }))
-        continue;
-
-      // Otherwise we should go visit the referred to function.
-      Visited.insert(BA->getFunction());
-      Worklist.push_back(BA->getFunction());
+    // blockaddresses are weird and don't participate in the call graph anyway,
+    // skip them.
+    if (isa<BlockAddress>(C))
       continue;
-    }
 
     for (Value *Op : C->operand_values())
       if (Visited.insert(cast<Constant>(Op)).second)

diff  --git a/llvm/test/Analysis/LazyCallGraph/blockaddress.ll b/llvm/test/Analysis/LazyCallGraph/blockaddress.ll
new file mode 100644
index 0000000000000..cf2d00bce6db8
--- /dev/null
+++ b/llvm/test/Analysis/LazyCallGraph/blockaddress.ll
@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes="cgscc(function(sccp,simplifycfg))" < %s -S | FileCheck %s
+
+define i32 @baz(i32 %y, i1 %b) {
+; CHECK-LABEL: @baz(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[B:%.*]], label [[LAB:%.*]], label [[FOR_COND:%.*]]
+; CHECK:       for.cond:
+; CHECK-NEXT:    [[P_0:%.*]] = phi i8* [ null, [[FOR_COND]] ], [ blockaddress(@baz, [[LAB]]), [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[INCDEC_PTR:%.*]] = getelementptr inbounds i8, i8* [[P_0]], i64 1
+; CHECK-NEXT:    br label [[FOR_COND]]
+; CHECK:       lab:
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  br i1 %b, label %lab, label %for.cond.preheader
+
+for.cond.preheader:
+  br label %for.cond
+
+for.cond:
+  %p.0 = phi i8* [ null, %for.cond ], [ blockaddress(@baz, %lab), %for.cond.preheader ]
+  %incdec.ptr = getelementptr inbounds i8, i8* %p.0, i64 1
+  br label %for.cond
+
+lab:
+  ret i32 0
+}

diff  --git a/llvm/test/Transforms/Attributor/IPConstantProp/dangling-block-address.ll b/llvm/test/Transforms/Attributor/IPConstantProp/dangling-block-address.ll
index 3ddf81dfc1ac7..c4ae94bdd9100 100644
--- a/llvm/test/Transforms/Attributor/IPConstantProp/dangling-block-address.ll
+++ b/llvm/test/Transforms/Attributor/IPConstantProp/dangling-block-address.ll
@@ -34,37 +34,23 @@ entry:
 }
 
 define internal void @bar(i32* nocapture %pc) nounwind readonly {
-; IS__CGSCC_OPM: Function Attrs: nounwind readonly
-; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bar
-; IS__CGSCC_OPM-SAME: (i32* nocapture [[PC:%.*]]) #[[ATTR1:[0-9]+]] {
-; IS__CGSCC_OPM-NEXT:  entry:
-; IS__CGSCC_OPM-NEXT:    br label [[INDIRECTGOTO:%.*]]
-; IS__CGSCC_OPM:       lab0:
-; IS__CGSCC_OPM-NEXT:    [[INDVAR_NEXT:%.*]] = add i32 [[INDVAR:%.*]], 1
-; IS__CGSCC_OPM-NEXT:    br label [[INDIRECTGOTO]]
-; IS__CGSCC_OPM:       end:
-; IS__CGSCC_OPM-NEXT:    ret void
-; IS__CGSCC_OPM:       indirectgoto:
-; IS__CGSCC_OPM-NEXT:    [[INDVAR]] = phi i32 [ [[INDVAR_NEXT]], [[LAB0:%.*]] ], [ 0, [[ENTRY:%.*]] ]
-; IS__CGSCC_OPM-NEXT:    [[PC_ADDR_0:%.*]] = getelementptr i32, i32* [[PC]], i32 [[INDVAR]]
-; IS__CGSCC_OPM-NEXT:    [[TMP1_PN:%.*]] = load i32, i32* [[PC_ADDR_0]], align 4
-; IS__CGSCC_OPM-NEXT:    [[INDIRECT_GOTO_DEST_IN:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* @bar.l, i32 0, i32 [[TMP1_PN]]
-; IS__CGSCC_OPM-NEXT:    [[INDIRECT_GOTO_DEST:%.*]] = load i8*, i8** [[INDIRECT_GOTO_DEST_IN]], align 8
-; IS__CGSCC_OPM-NEXT:    indirectbr i8* [[INDIRECT_GOTO_DEST]], [label [[LAB0]], label %end]
-;
-; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone
-; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@bar
-; IS__CGSCC_NPM-SAME: () #[[ATTR1:[0-9]+]] {
-; IS__CGSCC_NPM-NEXT:  entry:
-; IS__CGSCC_NPM-NEXT:    br label [[INDIRECTGOTO:%.*]]
-; IS__CGSCC_NPM:       lab0:
-; IS__CGSCC_NPM-NEXT:    [[INDVAR_NEXT:%.*]] = add i32 [[INDVAR:%.*]], 1
-; IS__CGSCC_NPM-NEXT:    br label [[INDIRECTGOTO]]
-; IS__CGSCC_NPM:       end:
-; IS__CGSCC_NPM-NEXT:    ret void
-; IS__CGSCC_NPM:       indirectgoto:
-; IS__CGSCC_NPM-NEXT:    [[INDVAR]] = phi i32 [ [[INDVAR_NEXT]], [[LAB0:%.*]] ], [ 0, [[ENTRY:%.*]] ]
-; IS__CGSCC_NPM-NEXT:    indirectbr i8* undef, [label [[LAB0]], label %end]
+; IS__CGSCC____: Function Attrs: nounwind readonly
+; IS__CGSCC____-LABEL: define {{[^@]+}}@bar
+; IS__CGSCC____-SAME: (i32* nocapture [[PC:%.*]]) #[[ATTR1:[0-9]+]] {
+; IS__CGSCC____-NEXT:  entry:
+; IS__CGSCC____-NEXT:    br label [[INDIRECTGOTO:%.*]]
+; IS__CGSCC____:       lab0:
+; IS__CGSCC____-NEXT:    [[INDVAR_NEXT:%.*]] = add i32 [[INDVAR:%.*]], 1
+; IS__CGSCC____-NEXT:    br label [[INDIRECTGOTO]]
+; IS__CGSCC____:       end:
+; IS__CGSCC____-NEXT:    ret void
+; IS__CGSCC____:       indirectgoto:
+; IS__CGSCC____-NEXT:    [[INDVAR]] = phi i32 [ [[INDVAR_NEXT]], [[LAB0:%.*]] ], [ 0, [[ENTRY:%.*]] ]
+; IS__CGSCC____-NEXT:    [[PC_ADDR_0:%.*]] = getelementptr i32, i32* [[PC]], i32 [[INDVAR]]
+; IS__CGSCC____-NEXT:    [[TMP1_PN:%.*]] = load i32, i32* [[PC_ADDR_0]], align 4
+; IS__CGSCC____-NEXT:    [[INDIRECT_GOTO_DEST_IN:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* @bar.l, i32 0, i32 [[TMP1_PN]]
+; IS__CGSCC____-NEXT:    [[INDIRECT_GOTO_DEST:%.*]] = load i8*, i8** [[INDIRECT_GOTO_DEST_IN]], align 8
+; IS__CGSCC____-NEXT:    indirectbr i8* [[INDIRECT_GOTO_DEST]], [label [[LAB0]], label %end]
 ;
 entry:
   br label %indirectgoto
@@ -104,11 +90,7 @@ entry:
 ;.
 ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn }
 ;.
-; IS__CGSCC_OPM: attributes #[[ATTR0]] = { nounwind readnone }
-; IS__CGSCC_OPM: attributes #[[ATTR1]] = { nounwind readonly }
-; IS__CGSCC_OPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn }
-;.
-; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nounwind readnone }
-; IS__CGSCC_NPM: attributes #[[ATTR1]] = { nofree norecurse nosync nounwind readnone }
-; IS__CGSCC_NPM: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn }
+; IS__CGSCC____: attributes #[[ATTR0]] = { nounwind readnone }
+; IS__CGSCC____: attributes #[[ATTR1]] = { nounwind readonly }
+; IS__CGSCC____: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn }
 ;.

diff  --git a/llvm/test/Transforms/Attributor/liveness.ll b/llvm/test/Transforms/Attributor/liveness.ll
index fcb6530c63339..30e2fd69cef5a 100644
--- a/llvm/test/Transforms/Attributor/liveness.ll
+++ b/llvm/test/Transforms/Attributor/liveness.ll
@@ -2432,9 +2432,9 @@ define internal void @dead_with_blockaddress_users(i32* nocapture %pc) nounwind
 ; IS__CGSCC_OPM-NEXT:    [[INDIRECT_GOTO_DEST:%.*]] = load i8*, i8** [[INDIRECT_GOTO_DEST_IN]]
 ; IS__CGSCC_OPM-NEXT:    indirectbr i8* [[INDIRECT_GOTO_DEST]], [label [[LAB0]], label %end]
 ;
-; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone
+; IS__CGSCC____: Function Attrs: nounwind readonly
 ; IS__CGSCC____-LABEL: define {{[^@]+}}@dead_with_blockaddress_users
-; IS__CGSCC____-SAME: () #[[ATTR14:[0-9]+]] {
+; IS__CGSCC____-SAME: (i32* nocapture [[PC:%.*]]) #[[ATTR14:[0-9]+]] {
 ; IS__CGSCC____-NEXT:  entry:
 ; IS__CGSCC____-NEXT:    br label [[INDIRECTGOTO:%.*]]
 ; IS__CGSCC____:       lab0:
@@ -2444,7 +2444,11 @@ define internal void @dead_with_blockaddress_users(i32* nocapture %pc) nounwind
 ; IS__CGSCC____-NEXT:    ret void
 ; IS__CGSCC____:       indirectgoto:
 ; IS__CGSCC____-NEXT:    [[INDVAR]] = phi i32 [ [[INDVAR_NEXT]], [[LAB0:%.*]] ], [ 0, [[ENTRY:%.*]] ]
-; IS__CGSCC____-NEXT:    indirectbr i8* undef, [label [[LAB0]], label %end]
+; IS__CGSCC____-NEXT:    [[PC_ADDR_0:%.*]] = getelementptr i32, i32* [[PC]], i32 [[INDVAR]]
+; IS__CGSCC____-NEXT:    [[TMP1_PN:%.*]] = load i32, i32* [[PC_ADDR_0]], align 4
+; IS__CGSCC____-NEXT:    [[INDIRECT_GOTO_DEST_IN:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* @dead_with_blockaddress_users.l, i32 0, i32 [[TMP1_PN]]
+; IS__CGSCC____-NEXT:    [[INDIRECT_GOTO_DEST:%.*]] = load i8*, i8** [[INDIRECT_GOTO_DEST_IN]], align 8
+; IS__CGSCC____-NEXT:    indirectbr i8* [[INDIRECT_GOTO_DEST]], [label [[LAB0]], label %end]
 ;
 entry:
   br label %indirectgoto
@@ -2681,7 +2685,7 @@ declare void @llvm.lifetime.end.p0i8(i64 %0, i8* %1)
 ; IS__CGSCC____: attributes #[[ATTR11]] = { nofree norecurse noreturn nosync nounwind readnone }
 ; IS__CGSCC____: attributes #[[ATTR12]] = { nofree norecurse noreturn nosync nounwind readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR13]] = { nofree nosync nounwind willreturn }
-; IS__CGSCC____: attributes #[[ATTR14]] = { nofree norecurse nosync nounwind readnone }
+; IS__CGSCC____: attributes #[[ATTR14]] = { nounwind readonly }
 ; IS__CGSCC____: attributes #[[ATTR15]] = { nofree nosync nounwind readnone willreturn }
 ; IS__CGSCC____: attributes #[[ATTR16:[0-9]+]] = { argmemonly nofree nosync nounwind willreturn }
 ; IS__CGSCC____: attributes #[[ATTR17]] = { nounwind willreturn }

diff  --git a/llvm/unittests/Analysis/LazyCallGraphTest.cpp b/llvm/unittests/Analysis/LazyCallGraphTest.cpp
index b154c6f290889..d6e73f3a95f2a 100644
--- a/llvm/unittests/Analysis/LazyCallGraphTest.cpp
+++ b/llvm/unittests/Analysis/LazyCallGraphTest.cpp
@@ -1978,7 +1978,8 @@ TEST(LazyCallGraphTest, HandleBlockAddress) {
   LazyCallGraph::Node &G = *CG.lookup(lookupFunction(*M, "g"));
   EXPECT_EQ(&FRC, CG.lookupRefSCC(F));
   EXPECT_EQ(&GRC, CG.lookupRefSCC(G));
-  EXPECT_TRUE(GRC.isParentOf(FRC));
+  EXPECT_FALSE(GRC.isParentOf(FRC));
+  EXPECT_FALSE(FRC.isParentOf(GRC));
 }
 
 // Test that a blockaddress that refers to itself creates no new RefSCC


        


More information about the llvm-commits mailing list