Skip to content

[SimplifyCFG] Remove limitation on sinking of load/store of alloca #104788

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 26, 2024

Conversation

nikic
Copy link
Contributor

@nikic nikic commented Aug 19, 2024

This is a followup to #104579 to remove the limitation on sinking loads/stores of allocas entirely, even if this would introduce a phi node.

Nowadays, SROA supports speculating load/store over select/phi. Additionally, SimplifyCFG with sinking only runs at the end of the function simplification pipeline, after SROA. I checked that the two tests modified here still successfully SROA after the SimplifyCFG transform.

We should, however, keep the limitation on lifetime intrinsics. SROA does not have speculation support for these, and I've also found that the way these are handled in the backend is very problematic (#104776), so I think we should leave them alone.

This is a followup to llvm#104579
to remove the limitation on sinking loads/stores of allocas entirely,
even if this would introduce a phi node.

Nowdays, SROA support speculating load/store over select/phi.
Additionally, SimplifyCFG with sinking only runs at the end of
the function simplification pipeline, after SROA. I checked that
the two tests modified here still successfully SROA after the
SimplifyCFG transform.

We should, however, keep the limitation on lifetime intrinsics.
SROA does not have speculation support for these, and I've also
found that the way these are handled in the backend is very
problematic (llvm#104776),
so I think we should leave them alone.
@llvmbot
Copy link
Member

llvmbot commented Aug 19, 2024

@llvm/pr-subscribers-llvm-transforms

Author: Nikita Popov (nikic)

Changes

This is a followup to #104579 to remove the limitation on sinking loads/stores of allocas entirely, even if this would introduce a phi node.

Nowadays, SROA supports speculating load/store over select/phi. Additionally, SimplifyCFG with sinking only runs at the end of the function simplification pipeline, after SROA. I checked that the two tests modified here still successfully SROA after the SimplifyCFG transform.

We should, however, keep the limitation on lifetime intrinsics. SROA does not have speculation support for these, and I've also found that the way these are handled in the backend is very problematic (#104776), so I think we should leave them alone.


Full diff: https://github.com/llvm/llvm-project/pull/104788.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/Utils/SimplifyCFG.cpp (+4-15)
  • (modified) llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll (+6-15)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index ebdf760bda7f1a..3f680de98470ca 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -2031,21 +2031,10 @@ static bool canSinkInstructions(
       return I->getOperand(OI) == I0->getOperand(OI);
     };
     if (!all_of(Insts, SameAsI0)) {
-      // Because SROA historically couldn't handle speculating stores of
-      // selects, we try not to sink loads, stores or lifetime markers of
-      // allocas when we'd have to create a PHI for the address operand.
-      // TODO: SROA supports speculation for loads and stores now -- remove
-      // this hack?
-      if (isa<StoreInst>(I0) && OI == 1 &&
-          any_of(Insts, [](const Instruction *I) {
-            return isa<AllocaInst>(I->getOperand(1)->stripPointerCasts());
-          }))
-        return false;
-      if (isa<LoadInst>(I0) && OI == 0 &&
-          any_of(Insts, [](const Instruction *I) {
-            return isa<AllocaInst>(I->getOperand(0)->stripPointerCasts());
-          }))
-        return false;
+      // SROA can't speculate lifetime markers of selects/phis, and the
+      // backend may handle such lifetimes incorrectly as well (#104776).
+      // Don't sink lifetimes if it would introduce a phi on the pointer
+      // argument.
       if (isLifeTimeMarker(I0) && OI == 1 &&
           any_of(Insts, [](const Instruction *I) {
             return isa<AllocaInst>(I->getOperand(1)->stripPointerCasts());
diff --git a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
index cd26d949836e68..39b1bec164b9e5 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/sink-common-code.ll
@@ -801,14 +801,8 @@ define i32 @test_pr30188(i1 zeroext %flag, i32 %x) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[Y:%.*]] = alloca i32, align 4
 ; CHECK-NEXT:    [[Z:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
-; CHECK:       if.then:
-; CHECK-NEXT:    store i32 [[X:%.*]], ptr [[Y]], align 4
-; CHECK-NEXT:    br label [[IF_END:%.*]]
-; CHECK:       if.else:
-; CHECK-NEXT:    store i32 [[X]], ptr [[Z]], align 4
-; CHECK-NEXT:    br label [[IF_END]]
-; CHECK:       if.end:
+; CHECK-NEXT:    [[Y_Z:%.*]] = select i1 [[FLAG:%.*]], ptr [[Y]], ptr [[Z]]
+; CHECK-NEXT:    store i32 [[X:%.*]], ptr [[Y_Z]], align 4
 ; CHECK-NEXT:    ret i32 1
 ;
 entry:
@@ -834,17 +828,14 @@ define i32 @test_pr30188a(i1 zeroext %flag, i32 %x) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[Y:%.*]] = alloca i32, align 4
 ; CHECK-NEXT:    [[Z:%.*]] = alloca i32, align 4
-; CHECK-NEXT:    br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK-NEXT:    br i1 [[FLAG:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
 ; CHECK:       if.then:
 ; CHECK-NEXT:    call void @g()
-; CHECK-NEXT:    [[ONE:%.*]] = load i32, ptr [[Y]], align 4
-; CHECK-NEXT:    br label [[IF_END:%.*]]
-; CHECK:       if.else:
-; CHECK-NEXT:    [[THREE:%.*]] = load i32, ptr [[Z]], align 4
 ; CHECK-NEXT:    br label [[IF_END]]
 ; CHECK:       if.end:
-; CHECK-NEXT:    [[THREE_SINK:%.*]] = phi i32 [ [[THREE]], [[IF_ELSE]] ], [ [[ONE]], [[IF_THEN]] ]
-; CHECK-NEXT:    [[FOUR:%.*]] = add i32 [[THREE_SINK]], 2
+; CHECK-NEXT:    [[Z_SINK:%.*]] = phi ptr [ [[Y]], [[IF_THEN]] ], [ [[Z]], [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[THREE:%.*]] = load i32, ptr [[Z_SINK]], align 4
+; CHECK-NEXT:    [[FOUR:%.*]] = add i32 [[THREE]], 2
 ; CHECK-NEXT:    store i32 [[FOUR]], ptr [[Y]], align 4
 ; CHECK-NEXT:    ret i32 1
 ;

dtcxzyw added a commit to dtcxzyw/llvm-opt-benchmark that referenced this pull request Aug 20, 2024
Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@nikic nikic merged commit 84497c6 into llvm:main Aug 26, 2024
10 checks passed
@nikic nikic deleted the simplifycfg-sink-alloca-full branch August 26, 2024 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants