[llvm] 330cb03 - [LoadStoreVectorizer] Check for guaranteed-to-transfer (PR52950)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 3 01:57:03 PST 2022


Author: Nikita Popov
Date: 2022-01-03T10:55:47+01:00
New Revision: 330cb0326911ca7090be56c1641ba86f26b6c3c8

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

LOG: [LoadStoreVectorizer] Check for guaranteed-to-transfer (PR52950)

Rather than checking for nounwind in particular, make sure the
instruction is guaranteed to transfer execution, which will also
handle non-willreturn calls correctly.

Fixes https://github.com/llvm/llvm-project/issues/52950.

Added: 
    

Modified: 
    llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp
    llvm/test/Transforms/LoadStoreVectorizer/NVPTX/merge-across-side-effects.ll
    llvm/test/Transforms/LoadStoreVectorizer/int_sideeffect.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp b/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp
index 5a4a2f0924f68..d2e0d1d474b0e 100644
--- a/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoadStoreVectorizer.cpp
@@ -698,8 +698,9 @@ Vectorizer::getVectorizablePrefix(ArrayRef<Instruction *> Chain) {
       ChainInstrs.push_back(&I);
       continue;
     }
-    if (I.mayThrow()) {
-      LLVM_DEBUG(dbgs() << "LSV: Found may-throw operation: " << I << '\n');
+    if (!isGuaranteedToTransferExecutionToSuccessor(&I)) {
+      LLVM_DEBUG(dbgs() << "LSV: Found instruction may not transfer execution: "
+                        << I << '\n');
       break;
     }
     if (I.mayReadOrWriteMemory())

diff  --git a/llvm/test/Transforms/LoadStoreVectorizer/NVPTX/merge-across-side-effects.ll b/llvm/test/Transforms/LoadStoreVectorizer/NVPTX/merge-across-side-effects.ll
index 72c13b4d12e52..73623dade42f9 100644
--- a/llvm/test/Transforms/LoadStoreVectorizer/NVPTX/merge-across-side-effects.ll
+++ b/llvm/test/Transforms/LoadStoreVectorizer/NVPTX/merge-across-side-effects.ll
@@ -200,10 +200,10 @@ define void @store_fn_readnone(i32* %p) #0 {
 }
 
 
-attributes #0 = { nounwind }
-attributes #1 = { nounwind writeonly }
-attributes #2 = { nounwind readonly }
+attributes #0 = { nounwind willreturn }
+attributes #1 = { nounwind willreturn writeonly }
+attributes #2 = { nounwind readonly willreturn }
 attributes #3 = { writeonly }
 attributes #4 = { readonly }
 ; readnone implies nounwind, so no need to test separately
-attributes #5 = { nounwind readnone }
+attributes #5 = { nounwind willreturn readnone }

diff  --git a/llvm/test/Transforms/LoadStoreVectorizer/int_sideeffect.ll b/llvm/test/Transforms/LoadStoreVectorizer/int_sideeffect.ll
index 23108e308f816..bd47d66ddaaa4 100644
--- a/llvm/test/Transforms/LoadStoreVectorizer/int_sideeffect.ll
+++ b/llvm/test/Transforms/LoadStoreVectorizer/int_sideeffect.ll
@@ -44,8 +44,8 @@ define void @test_sideeffect(float* %p) {
 
 declare void @foo()
 
-define void @test_inaccessiblememonly(float* %p) {
-; CHECK-LABEL: @test_inaccessiblememonly(
+define void @test_inaccessiblememonly_nounwind_willreturn(float* %p) {
+; CHECK-LABEL: @test_inaccessiblememonly_nounwind_willreturn(
 ; CHECK-NEXT:    [[P0:%.*]] = getelementptr float, float* [[P:%.*]], i64 0
 ; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float* [[P0]] to <4 x float>*
 ; CHECK-NEXT:    [[TMP2:%.*]] = load <4 x float>, <4 x float>* [[TMP1]], align 16
@@ -62,6 +62,41 @@ define void @test_inaccessiblememonly(float* %p) {
 ; CHECK-NEXT:    [[TMP7:%.*]] = bitcast float* [[P0]] to <4 x float>*
 ; CHECK-NEXT:    store <4 x float> [[TMP6]], <4 x float>* [[TMP7]], align 16
 ; CHECK-NEXT:    ret void
+;
+  %p0 = getelementptr float, float* %p, i64 0
+  %p1 = getelementptr float, float* %p, i64 1
+  %p2 = getelementptr float, float* %p, i64 2
+  %p3 = getelementptr float, float* %p, i64 3
+  %l0 = load float, float* %p0, align 16
+  %l1 = load float, float* %p1
+  %l2 = load float, float* %p2
+  call void @foo() inaccessiblememonly nounwind willreturn
+  %l3 = load float, float* %p3
+  store float %l0, float* %p0, align 16
+  call void @foo() inaccessiblememonly nounwind willreturn
+  store float %l1, float* %p1
+  store float %l2, float* %p2
+  store float %l3, float* %p3
+  ret void
+}
+
+define void @test_inaccessiblememonly_not_willreturn(float* %p) {
+; CHECK-LABEL: @test_inaccessiblememonly_not_willreturn(
+; CHECK-NEXT:    [[P0:%.*]] = getelementptr float, float* [[P:%.*]], i64 0
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr float, float* [[P]], i64 1
+; CHECK-NEXT:    [[P2:%.*]] = getelementptr float, float* [[P]], i64 2
+; CHECK-NEXT:    [[P3:%.*]] = getelementptr float, float* [[P]], i64 3
+; CHECK-NEXT:    [[L0:%.*]] = load float, float* [[P0]], align 16
+; CHECK-NEXT:    [[L1:%.*]] = load float, float* [[P1]], align 4
+; CHECK-NEXT:    [[L2:%.*]] = load float, float* [[P2]], align 4
+; CHECK-NEXT:    call void @foo() #[[ATTR2:[0-9]+]]
+; CHECK-NEXT:    [[L3:%.*]] = load float, float* [[P3]], align 4
+; CHECK-NEXT:    store float [[L0]], float* [[P0]], align 16
+; CHECK-NEXT:    call void @foo() #[[ATTR2]]
+; CHECK-NEXT:    store float [[L1]], float* [[P1]], align 4
+; CHECK-NEXT:    store float [[L2]], float* [[P2]], align 4
+; CHECK-NEXT:    store float [[L3]], float* [[P3]], align 4
+; CHECK-NEXT:    ret void
 ;
   %p0 = getelementptr float, float* %p, i64 0
   %p1 = getelementptr float, float* %p, i64 1
@@ -79,3 +114,38 @@ define void @test_inaccessiblememonly(float* %p) {
   store float %l3, float* %p3
   ret void
 }
+
+define void @test_inaccessiblememonly_not_nounwind(float* %p) {
+; CHECK-LABEL: @test_inaccessiblememonly_not_nounwind(
+; CHECK-NEXT:    [[P0:%.*]] = getelementptr float, float* [[P:%.*]], i64 0
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr float, float* [[P]], i64 1
+; CHECK-NEXT:    [[P2:%.*]] = getelementptr float, float* [[P]], i64 2
+; CHECK-NEXT:    [[P3:%.*]] = getelementptr float, float* [[P]], i64 3
+; CHECK-NEXT:    [[L0:%.*]] = load float, float* [[P0]], align 16
+; CHECK-NEXT:    [[L1:%.*]] = load float, float* [[P1]], align 4
+; CHECK-NEXT:    [[L2:%.*]] = load float, float* [[P2]], align 4
+; CHECK-NEXT:    call void @foo() #[[ATTR3:[0-9]+]]
+; CHECK-NEXT:    [[L3:%.*]] = load float, float* [[P3]], align 4
+; CHECK-NEXT:    store float [[L0]], float* [[P0]], align 16
+; CHECK-NEXT:    call void @foo() #[[ATTR3]]
+; CHECK-NEXT:    store float [[L1]], float* [[P1]], align 4
+; CHECK-NEXT:    store float [[L2]], float* [[P2]], align 4
+; CHECK-NEXT:    store float [[L3]], float* [[P3]], align 4
+; CHECK-NEXT:    ret void
+;
+  %p0 = getelementptr float, float* %p, i64 0
+  %p1 = getelementptr float, float* %p, i64 1
+  %p2 = getelementptr float, float* %p, i64 2
+  %p3 = getelementptr float, float* %p, i64 3
+  %l0 = load float, float* %p0, align 16
+  %l1 = load float, float* %p1
+  %l2 = load float, float* %p2
+  call void @foo() inaccessiblememonly willreturn
+  %l3 = load float, float* %p3
+  store float %l0, float* %p0, align 16
+  call void @foo() inaccessiblememonly willreturn
+  store float %l1, float* %p1
+  store float %l2, float* %p2
+  store float %l3, float* %p3
+  ret void
+}


        


More information about the llvm-commits mailing list