[llvm] dcc7706 - [InstCombine] Remove unused llvm.experimental.noalias.scope.decl

Jeroen Dobbelaere via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 24 04:58:40 PST 2021


Author: Jeroen Dobbelaere
Date: 2021-01-24T13:55:50+01:00
New Revision: dcc7706fcf2438b92d6f619e63c5db4880042ed2

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

LOG: [InstCombine] Remove unused llvm.experimental.noalias.scope.decl

A @llvm.experimental.noalias.scope.decl is only useful if there is !alias.scope and !noalias metadata that uses the declared scope.
When that is not the case for at least one of the two, the intrinsic call can as well be removed.

Reviewed By: nikic

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

Added: 
    llvm/test/Transforms/InstCombine/noalias-scope-decl.ll

Modified: 
    llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
    llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll
    llvm/test/Transforms/Coroutines/coro-retcon-value.ll
    llvm/test/Transforms/Coroutines/coro-retcon.ll
    llvm/test/Transforms/Coroutines/ex2.ll
    llvm/test/Transforms/Coroutines/ex3.ll
    llvm/test/Transforms/Coroutines/ex4.ll
    llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll
    llvm/test/Transforms/PhaseOrdering/instcombine-sroa-inttoptr.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 2f8a80a89992..518e909e8ab4 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -3766,6 +3766,55 @@ bool InstCombinerImpl::run() {
   return MadeIRChange;
 }
 
+// Track the scopes used by !alias.scope and !noalias. In a function, a
+// @llvm.experimental.noalias.scope.decl is only useful if that scope is used
+// by both sets. If not, the declaration of the scope can be safely omitted.
+// The MDNode of the scope can be omitted as well for the instructions that are
+// part of this function. We do not do that at this point, as this might become
+// too time consuming to do.
+class AliasScopeTracker {
+  SmallPtrSet<const MDNode *, 8> UsedAliasScopesAndLists;
+  SmallPtrSet<const MDNode *, 8> UsedNoAliasScopesAndLists;
+
+public:
+  void analyse(Instruction *I) {
+    // This seems to be faster than checking 'mayReadOrWriteMemory()'.
+    if (!I->hasMetadataOtherThanDebugLoc())
+      return;
+
+    auto Track = [](Metadata *ScopeList, auto &Container) {
+      const auto *MDScopeList = dyn_cast_or_null<MDNode>(ScopeList);
+      if (!MDScopeList || !Container.insert(MDScopeList).second)
+        return;
+      for (auto &MDOperand : MDScopeList->operands())
+        if (auto *MDScope = dyn_cast<MDNode>(MDOperand))
+          Container.insert(MDScope);
+    };
+
+    Track(I->getMetadata(LLVMContext::MD_alias_scope), UsedAliasScopesAndLists);
+    Track(I->getMetadata(LLVMContext::MD_noalias), UsedNoAliasScopesAndLists);
+  }
+
+  bool isNoAliasScopeDeclDead(Instruction *Inst) {
+    NoAliasScopeDeclInst *Decl = dyn_cast<NoAliasScopeDeclInst>(Inst);
+    if (!Decl)
+      return false;
+
+    assert(Decl->use_empty() &&
+           "llvm.experimental.noalias.scope.decl in use ?");
+    const MDNode *MDSL = Decl->getScopeList();
+    assert(MDSL->getNumOperands() == 1 &&
+           "llvm.experimental.noalias.scope should refer to a single scope");
+    auto &MDOperand = MDSL->getOperand(0);
+    if (auto *MD = dyn_cast<MDNode>(MDOperand))
+      return !UsedAliasScopesAndLists.contains(MD) ||
+             !UsedNoAliasScopesAndLists.contains(MD);
+
+    // Not an MDNode ? throw away.
+    return true;
+  }
+};
+
 /// Populate the IC worklist from a function, by walking it in depth-first
 /// order and adding all reachable code to the worklist.
 ///
@@ -3784,6 +3833,7 @@ static bool prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
 
   SmallVector<Instruction*, 128> InstrsForInstCombineWorklist;
   DenseMap<Constant *, Constant *> FoldedConstants;
+  AliasScopeTracker SeenAliasScopes;
 
   do {
     BasicBlock *BB = Worklist.pop_back_val();
@@ -3830,8 +3880,10 @@ static bool prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
 
       // Skip processing debug intrinsics in InstCombine. Processing these call instructions
       // consumes non-trivial amount of time and provides no value for the optimization.
-      if (!isa<DbgInfoIntrinsic>(Inst))
+      if (!isa<DbgInfoIntrinsic>(Inst)) {
         InstrsForInstCombineWorklist.push_back(Inst);
+        SeenAliasScopes.analyse(Inst);
+      }
     }
 
     // Recursively visit successors.  If this is a branch or switch on a
@@ -3879,7 +3931,8 @@ static bool prepareICWorklistFromFunction(Function &F, const DataLayout &DL,
   for (Instruction *Inst : reverse(InstrsForInstCombineWorklist)) {
     // DCE instruction if trivially dead. As we iterate in reverse program
     // order here, we will clean up whole chains of dead instructions.
-    if (isInstructionTriviallyDead(Inst, TLI)) {
+    if (isInstructionTriviallyDead(Inst, TLI) ||
+        SeenAliasScopes.isNoAliasScopeDeclDead(Inst)) {
       ++NumDeadInst;
       LLVM_DEBUG(dbgs() << "IC: DCE: " << *Inst << '\n');
       salvageDebugInfo(*Inst);

diff  --git a/llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll b/llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll
index 993fc5d01aec..c76ad50a88b9 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll
@@ -67,10 +67,7 @@ entry:
 ; CHECK-NEXT:  entry:
 ; CHECK:         [[BUFFER:%.*]] = alloca [8 x i8], align 4
 ; CHECK:         [[SLOT:%.*]] = bitcast [8 x i8]* [[BUFFER]] to i32*
-; CHECK-NEXT:    call void @llvm.experimental.noalias.scope.decl
-; CHECK-NEXT:    call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT:    store i32 7, i32* [[SLOT]], align 4
-; CHECK-NEXT:    call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT:    call void @print(i32 7)
 ; CHECK-NEXT:    ret i32 0
 

diff  --git a/llvm/test/Transforms/Coroutines/coro-retcon-value.ll b/llvm/test/Transforms/Coroutines/coro-retcon-value.ll
index 42201a239f87..2c66b6af99c6 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon-value.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon-value.ll
@@ -79,17 +79,14 @@ entry:
 ; CHECK:         [[SLOT:%.*]] = bitcast [8 x i8]* [[BUFFER]] to i32*
 ; CHECK-NEXT:    store i32 4, i32* [[SLOT]], align 4
 ; CHECK-NEXT:    call void @print(i32 4)
-; CHECK-NEXT:    call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT:    [[LOAD:%.*]] = load i32, i32* [[SLOT]], align 4
 ; CHECK-NEXT:    [[INC:%.*]] = add i32 [[LOAD]], 1
 ; CHECK-NEXT:    store i32 [[INC]], i32* [[SLOT]], align 4
 ; CHECK-NEXT:    call void @print(i32 [[INC]])
-; CHECK-NEXT:    call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT:    [[LOAD:%.*]] = load i32, i32* [[SLOT]], align 4
 ; CHECK-NEXT:    [[INC:%.*]] = add i32 [[LOAD]], 1
 ; CHECK-NEXT:    store i32 [[INC]], i32* [[SLOT]], align 4
 ; CHECK-NEXT:    call void @print(i32 [[INC]])
-; CHECK-NEXT:    call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT:    ret i32 0
 
 declare token @llvm.coro.id.retcon(i32, i32, i8*, i8*, i8*, i8*)

diff  --git a/llvm/test/Transforms/Coroutines/coro-retcon.ll b/llvm/test/Transforms/Coroutines/coro-retcon.ll
index 2534af8494ea..48e0b644eb8d 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon.ll
@@ -78,7 +78,6 @@ entry:
 ; CHECK-NEXT:    [[LOAD:%.*]] = load i32, i32* [[SLOT]], align 4
 ; CHECK-NEXT:    [[INC:%.*]] = add i32 [[LOAD]], 1
 ; CHECK-NEXT:    call void @print(i32 [[INC]])
-; CHECK-NEXT:    call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT:    ret i32 0
 
 define hidden { i8*, i8* } @g(i8* %buffer, i16* %ptr) {

diff  --git a/llvm/test/Transforms/Coroutines/ex2.ll b/llvm/test/Transforms/Coroutines/ex2.ll
index 820f53814661..584bc909a4eb 100644
--- a/llvm/test/Transforms/Coroutines/ex2.ll
+++ b/llvm/test/Transforms/Coroutines/ex2.ll
@@ -49,9 +49,7 @@ return:
   ret i32 0
 ; CHECK-NOT:  call i8* @CustomAlloc
 ; CHECK:      call void @print(i32 4)
-; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT: call void @print(i32 5)
-; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT: call void @print(i32 6)
 ; CHECK-NEXT: ret i32 0
 }

diff  --git a/llvm/test/Transforms/Coroutines/ex3.ll b/llvm/test/Transforms/Coroutines/ex3.ll
index c75c7a1e09b1..85cf53fb576d 100644
--- a/llvm/test/Transforms/Coroutines/ex3.ll
+++ b/llvm/test/Transforms/Coroutines/ex3.ll
@@ -53,9 +53,7 @@ return:
   ret i32 0
 ; CHECK-NOT:  i8* @malloc
 ; CHECK:      call void @print(i32 4)
-; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT: call void @print(i32 -5)
-; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT: call void @print(i32 5)
 ; CHECK:      ret i32 0
 }

diff  --git a/llvm/test/Transforms/Coroutines/ex4.ll b/llvm/test/Transforms/Coroutines/ex4.ll
index 1a26107ecaf3..e60bc2c691fa 100644
--- a/llvm/test/Transforms/Coroutines/ex4.ll
+++ b/llvm/test/Transforms/Coroutines/ex4.ll
@@ -50,9 +50,7 @@ entry:
   call void @llvm.coro.destroy(i8* %hdl)
   ret i32 0
 ; CHECK:      call void @print(i32 4)
-; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT: call void @print(i32 5)
-; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl
 ; CHECK-NEXT: call void @print(i32 6)
 ; CHECK:      ret i32 0
 }

diff  --git a/llvm/test/Transforms/InstCombine/noalias-scope-decl.ll b/llvm/test/Transforms/InstCombine/noalias-scope-decl.ll
new file mode 100644
index 000000000000..1251579e596c
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/noalias-scope-decl.ll
@@ -0,0 +1,170 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -instcombine -S < %s | FileCheck %s
+
+define void @test01(i8* %ptr0, i8* %ptr1) {
+; CHECK-LABEL: @test01(
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1
+; CHECK-NEXT:    store i8 43, i8* [[PTR1:%.*]], align 1
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0
+  store i8 43, i8* %ptr1
+  ret void
+}
+
+define void @test02_keep(i8* %ptr0, i8* %ptr1) {
+; CHECK-LABEL: @test02_keep(
+; CHECK-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata !0)
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !alias.scope !0
+; CHECK-NEXT:    store i8 43, i8* [[PTR1:%.*]], align 1, !noalias !3
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !alias.scope !0
+  store i8 43, i8* %ptr1, !noalias !5
+  ret void
+}
+
+define void @test03(i8* %ptr0, i8* %ptr1) {
+; CHECK-LABEL: @test03(
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !alias.scope !4
+; CHECK-NEXT:    store i8 43, i8* [[PTR1:%.*]], align 1, !noalias !3
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !alias.scope !4
+  store i8 43, i8* %ptr1, !noalias !5
+  ret void
+}
+
+define void @test04_keep(i8* %ptr0, i8* %ptr1) {
+; CHECK-LABEL: @test04_keep(
+; CHECK-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata !0)
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !alias.scope !3
+; CHECK-NEXT:    store i8 43, i8* [[PTR1:%.*]], align 1, !noalias !3
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !alias.scope !5
+  store i8 43, i8* %ptr1, !noalias !5
+  ret void
+}
+
+define void @test05_keep(i8* %ptr0, i8* %ptr1) {
+; CHECK-LABEL: @test05_keep(
+; CHECK-NEXT:    call void @llvm.experimental.noalias.scope.decl(metadata !0)
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !alias.scope !3
+; CHECK-NEXT:    store i8 43, i8* [[PTR1:%.*]], align 1, !noalias !0
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !alias.scope !5
+  store i8 43, i8* %ptr1, !noalias !0
+  ret void
+}
+
+define void @test06(i8* %ptr0, i8* %ptr1) {
+; CHECK-LABEL: @test06(
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !alias.scope !3
+; CHECK-NEXT:    store i8 43, i8* [[PTR1:%.*]], align 1, !noalias !4
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !alias.scope !5
+  store i8 43, i8* %ptr1, !noalias !4
+  ret void
+}
+
+define void @test07(i8* %ptr0, i8* %ptr1) {
+; CHECK-LABEL: @test07(
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !alias.scope !0
+; CHECK-NEXT:    store i8 43, i8* [[PTR1:%.*]], align 1, !noalias !4
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !alias.scope !0
+  store i8 43, i8* %ptr1, !noalias !4
+  ret void
+}
+
+define void @test08(i8* %ptr0, i8* %ptr1) {
+; CHECK-LABEL: @test08(
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !alias.scope !4
+; CHECK-NEXT:    store i8 43, i8* [[PTR1:%.*]], align 1, !noalias !0
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !alias.scope !4
+  store i8 43, i8* %ptr1, !noalias !0
+  ret void
+}
+
+define void @test11(i8* %ptr0) {
+; CHECK-LABEL: @test11(
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !alias.scope !0
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !alias.scope !0
+  ret void
+}
+
+define void @test12(i8* %ptr0) {
+; CHECK-LABEL: @test12(
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !alias.scope !4
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !alias.scope !4
+  ret void
+}
+
+define void @test13(i8* %ptr0) {
+; CHECK-LABEL: @test13(
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !alias.scope !3
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !alias.scope !5
+  ret void
+}
+
+define void @test14(i8* %ptr0) {
+; CHECK-LABEL: @test14(
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !noalias !0
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !noalias !0
+  ret void
+}
+
+define void @test15(i8* %ptr0) {
+; CHECK-LABEL: @test15(
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !noalias !4
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !noalias !4
+  ret void
+}
+
+define void @test16(i8* %ptr0) {
+; CHECK-LABEL: @test16(
+; CHECK-NEXT:    store i8 42, i8* [[PTR0:%.*]], align 1, !noalias !3
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.experimental.noalias.scope.decl(metadata !0)
+  store i8 42, i8* %ptr0, !noalias !5
+  ret void
+}
+
+declare void @llvm.experimental.noalias.scope.decl(metadata)
+
+!0 = !{ !1 }
+!1 = distinct !{ !1, !2 }
+!2 = distinct !{ !2 }
+!3 = !{ !4 }
+!4 = distinct !{ !4, !2 }
+!5 = !{ !1, !4 }

diff  --git a/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll b/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll
index 9e96ba081bac..4fe75883959e 100644
--- a/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll
+++ b/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll
@@ -95,7 +95,6 @@ define internal void @callee2(i64* noalias sret(i64) align 32 %arg) {
 
 define amdgpu_kernel void @caller2() {
 ; CHECK-LABEL: @caller2(
-; CHECK-NEXT:    tail call void @llvm.experimental.noalias.scope.decl([[META0:metadata !.*]])
 ; CHECK-NEXT:    ret void
 ;
   %alloca = alloca i64, align 8, addrspace(5)

diff  --git a/llvm/test/Transforms/PhaseOrdering/instcombine-sroa-inttoptr.ll b/llvm/test/Transforms/PhaseOrdering/instcombine-sroa-inttoptr.ll
index 2ce1c49e04c4..9052fd5a03e4 100644
--- a/llvm/test/Transforms/PhaseOrdering/instcombine-sroa-inttoptr.ll
+++ b/llvm/test/Transforms/PhaseOrdering/instcombine-sroa-inttoptr.ll
@@ -70,7 +70,6 @@ define dso_local i32* @_Z3foo1S(%0* byval(%0) align 8 %arg) {
 ; CHECK-NEXT:    [[I2:%.*]] = alloca [[TMP0:%.*]], align 8
 ; CHECK-NEXT:    [[I1_SROA_0_0_I5_SROA_IDX:%.*]] = getelementptr inbounds [[TMP0]], %0* [[ARG:%.*]], i64 0, i32 0
 ; CHECK-NEXT:    [[I1_SROA_0_0_COPYLOAD:%.*]] = load i32*, i32** [[I1_SROA_0_0_I5_SROA_IDX]], align 8
-; CHECK-NEXT:    tail call void @llvm.experimental.noalias.scope.decl([[META0:metadata !.*]])
 ; CHECK-NEXT:    [[I_SROA_0_0_I6_SROA_IDX:%.*]] = getelementptr inbounds [[TMP0]], %0* [[I2]], i64 0, i32 0
 ; CHECK-NEXT:    store i32* [[I1_SROA_0_0_COPYLOAD]], i32** [[I_SROA_0_0_I6_SROA_IDX]], align 8
 ; CHECK-NEXT:    tail call void @_Z7escape01S(%0* nonnull byval(%0) align 8 [[I2]])
@@ -110,7 +109,6 @@ define dso_local i32* @_Z3bar1S(%0* byval(%0) align 8 %arg) {
 ; CHECK-NEXT:  bb:
 ; CHECK-NEXT:    [[I1_SROA_0_0_I4_SROA_IDX:%.*]] = getelementptr inbounds [[TMP0:%.*]], %0* [[ARG:%.*]], i64 0, i32 0
 ; CHECK-NEXT:    [[I1_SROA_0_0_COPYLOAD:%.*]] = load i32*, i32** [[I1_SROA_0_0_I4_SROA_IDX]], align 8
-; CHECK-NEXT:    tail call void @llvm.experimental.noalias.scope.decl([[META3:metadata !.*]])
 ; CHECK-NEXT:    [[I5:%.*]] = tail call i32 @_Z4condv()
 ; CHECK-NEXT:    [[I6_NOT:%.*]] = icmp eq i32 [[I5]], 0
 ; CHECK-NEXT:    br i1 [[I6_NOT]], label [[BB10:%.*]], label [[BB7:%.*]]


        


More information about the llvm-commits mailing list