From e322d1ebb7c2e690c00d2581ab128476ed962d63 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Tue, 30 Jan 2024 20:09:37 +0800 Subject: [PATCH 1/5] [CVP] Add pre-commit tests. NFC. --- .../CorrelatedValuePropagation/switch.ll | 295 ++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 llvm/test/Transforms/CorrelatedValuePropagation/switch.ll diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll b/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll new file mode 100644 index 00000000000000..1c3c818951a632 --- /dev/null +++ b/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll @@ -0,0 +1,295 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 +; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s + +define i32 @test_unreachable_default(i32 noundef %num) { +; CHECK-LABEL: define i32 @test_unreachable_default( +; CHECK-SAME: i32 noundef [[NUM:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2 +; CHECK-NEXT: switch i32 [[COND]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] +; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] +; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: [[CALL:%.*]] = call i32 @call0() +; CHECK-NEXT: br label [[CLEANUP:%.*]] +; CHECK: sw.bb2: +; CHECK-NEXT: [[CALL3:%.*]] = call i32 @call1() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: sw.bb4: +; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: sw.default: +; CHECK-NEXT: [[CALL6:%.*]] = call i32 @call3() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: cleanup: +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL6]], [[SW_DEFAULT]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] +; CHECK-NEXT: ret i32 [[RETVAL_0]] +; +entry: + %sub = add i32 %num, -120 + %cmp = icmp ult i32 %sub, 3 + %cond = select i1 %cmp, i32 %sub, i32 2 + switch i32 %cond, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb2 + i32 2, label %sw.bb4 + ] + +sw.bb: + %call = call i32 @call0() + br label %cleanup + +sw.bb2: + %call3 = call i32 @call1() + br label %cleanup + +sw.bb4: + %call5 = call i32 @call2() + br label %cleanup + +sw.default: + %call6 = call i32 @call3() + br label %cleanup + +cleanup: + %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ] + ret i32 %retval.0 +} + +define i32 @test_unreachable_default_shared_edge(i32 noundef %num) { +; CHECK-LABEL: define i32 @test_unreachable_default_shared_edge( +; CHECK-SAME: i32 noundef [[NUM:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2 +; CHECK-NEXT: switch i32 [[COND]], label [[SW_BB4:%.*]] [ +; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] +; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] +; CHECK-NEXT: i32 2, label [[SW_BB4]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: [[CALL:%.*]] = call i32 @call0() +; CHECK-NEXT: br label [[CLEANUP:%.*]] +; CHECK: sw.bb2: +; CHECK-NEXT: [[CALL3:%.*]] = call i32 @call1() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: sw.bb4: +; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: cleanup: +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] +; CHECK-NEXT: ret i32 [[RETVAL_0]] +; +entry: + %sub = add i32 %num, -120 + %cmp = icmp ult i32 %sub, 3 + %cond = select i1 %cmp, i32 %sub, i32 2 + switch i32 %cond, label %sw.bb4 [ + i32 0, label %sw.bb + i32 1, label %sw.bb2 + i32 2, label %sw.bb4 + ] + +sw.bb: + %call = call i32 @call0() + br label %cleanup + +sw.bb2: + %call3 = call i32 @call1() + br label %cleanup + +sw.bb4: + %call5 = call i32 @call2() + br label %cleanup + +cleanup: + %retval.0 = phi i32 [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ] + ret i32 %retval.0 +} + +; Negative tests + +define i32 @test_reachable_default(i32 noundef %num) { +; CHECK-LABEL: define i32 @test_reachable_default( +; CHECK-SAME: i32 noundef [[NUM:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 4 +; CHECK-NEXT: switch i32 [[COND]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] +; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] +; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: [[CALL:%.*]] = call i32 @call0() +; CHECK-NEXT: br label [[CLEANUP:%.*]] +; CHECK: sw.bb2: +; CHECK-NEXT: [[CALL3:%.*]] = call i32 @call1() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: sw.bb4: +; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: sw.default: +; CHECK-NEXT: [[CALL6:%.*]] = call i32 @call3() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: cleanup: +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL6]], [[SW_DEFAULT]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] +; CHECK-NEXT: ret i32 [[RETVAL_0]] +; +entry: + %sub = add i32 %num, -120 + %cmp = icmp ult i32 %sub, 3 + %cond = select i1 %cmp, i32 %sub, i32 4 + switch i32 %cond, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb2 + i32 2, label %sw.bb4 + ] + +sw.bb: + %call = call i32 @call0() + br label %cleanup + +sw.bb2: + %call3 = call i32 @call1() + br label %cleanup + +sw.bb4: + %call5 = call i32 @call2() + br label %cleanup + +sw.default: + %call6 = call i32 @call3() + br label %cleanup + +cleanup: + %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ] + ret i32 %retval.0 +} + +define i32 @test_unreachable_default_cond_may_be_undef(i32 %num) { +; CHECK-LABEL: define i32 @test_unreachable_default_cond_may_be_undef( +; CHECK-SAME: i32 [[NUM:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2 +; CHECK-NEXT: switch i32 [[COND]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] +; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] +; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: [[CALL:%.*]] = call i32 @call0() +; CHECK-NEXT: br label [[CLEANUP:%.*]] +; CHECK: sw.bb2: +; CHECK-NEXT: [[CALL3:%.*]] = call i32 @call1() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: sw.bb4: +; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: sw.default: +; CHECK-NEXT: [[CALL6:%.*]] = call i32 @call3() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: cleanup: +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL6]], [[SW_DEFAULT]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] +; CHECK-NEXT: ret i32 [[RETVAL_0]] +; +entry: + %sub = add i32 %num, -120 + %cmp = icmp ult i32 %sub, 3 + %cond = select i1 %cmp, i32 %sub, i32 2 + switch i32 %cond, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb2 + i32 2, label %sw.bb4 + ] + +sw.bb: + %call = call i32 @call0() + br label %cleanup + +sw.bb2: + %call3 = call i32 @call1() + br label %cleanup + +sw.bb4: + %call5 = call i32 @call2() + br label %cleanup + +sw.default: + %call6 = call i32 @call3() + br label %cleanup + +cleanup: + %retval.0 = phi i32 [ %call6, %sw.default ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ] + ret i32 %retval.0 +} + +define i32 @test_default_is_already_unreachable(i32 %num) { +; CHECK-LABEL: define i32 @test_default_is_already_unreachable( +; CHECK-SAME: i32 [[NUM:%.*]]) { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2 +; CHECK-NEXT: switch i32 [[COND]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] +; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] +; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] +; CHECK-NEXT: ] +; CHECK: sw.bb: +; CHECK-NEXT: [[CALL:%.*]] = call i32 @call0() +; CHECK-NEXT: br label [[CLEANUP:%.*]] +; CHECK: sw.bb2: +; CHECK-NEXT: [[CALL3:%.*]] = call i32 @call1() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: sw.bb4: +; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() +; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: sw.default: +; CHECK-NEXT: unreachable +; CHECK: cleanup: +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] +; CHECK-NEXT: ret i32 [[RETVAL_0]] +; +entry: + %sub = add i32 %num, -120 + %cmp = icmp ult i32 %sub, 3 + %cond = select i1 %cmp, i32 %sub, i32 2 + switch i32 %cond, label %sw.default [ + i32 0, label %sw.bb + i32 1, label %sw.bb2 + i32 2, label %sw.bb4 + ] + +sw.bb: + %call = call i32 @call0() + br label %cleanup + +sw.bb2: + %call3 = call i32 @call1() + br label %cleanup + +sw.bb4: + %call5 = call i32 @call2() + br label %cleanup + +sw.default: + unreachable + +cleanup: + %retval.0 = phi i32 [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ] + ret i32 %retval.0 +} + +declare i32 @call0() +declare i32 @call1() +declare i32 @call2() +declare i32 @call3() From 1636de95d142b0fdffb7e3b73ba3c3722695badf Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Tue, 30 Jan 2024 20:10:54 +0800 Subject: [PATCH 2/5] [CVP] Check whether the default case is reachable --- .../Scalar/CorrelatedValuePropagation.cpp | 31 +++++++++++++++++++ .../CorrelatedValuePropagation/basic.ll | 11 ++++--- .../CorrelatedValuePropagation/switch.ll | 12 ++++--- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index 9235850de92f3e..e1a5d83e4b96c2 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -371,6 +371,7 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI, { // Scope for SwitchInstProfUpdateWrapper. It must not live during // ConstantFoldTerminator() as the underlying SwitchInst can be changed. SwitchInstProfUpdateWrapper SI(*I); + unsigned ReachableCaseCount = 0; for (auto CI = SI->case_begin(), CE = SI->case_end(); CI != CE;) { ConstantInt *Case = CI->getCaseValue(); @@ -407,6 +408,35 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI, // Increment the case iterator since we didn't delete it. ++CI; + ++ReachableCaseCount; + } + + BasicBlock *DefaultDest = SI->getDefaultDest(); + if (!isa(DefaultDest->getFirstNonPHIOrDbg())) { + ConstantRange CR = LVI->getConstantRangeAtUse(I->getOperandUse(0), + /*UndefAllowed*/ false); + // The default dest is unreachable if all cases are covered. + if (!CR.isSizeLargerThan(ReachableCaseCount)) { + BasicBlock *NewUnreachableBB = + BasicBlock::Create(BB->getContext(), "default.unreachable", + BB->getParent(), DefaultDest); + new UnreachableInst(BB->getContext(), NewUnreachableBB); + + bool RemoveOldBB = --SuccessorsCount[DefaultDest] == 0; + + if (RemoveOldBB) + DefaultDest->removePredecessor(BB); + SI->setDefaultDest(NewUnreachableBB); + + if (RemoveOldBB) + DTU.applyUpdatesPermissive( + {{DominatorTree::Delete, BB, DefaultDest}}); + DTU.applyUpdatesPermissive( + {{DominatorTree::Insert, BB, NewUnreachableBB}}); + + ++NumDeadCases; + Changed = true; + } } } @@ -1227,6 +1257,7 @@ CorrelatedValuePropagationPass::run(Function &F, FunctionAnalysisManager &AM) { if (!Changed) { PA = PreservedAnalyses::all(); } else { + assert(DT->verify()); PA.preserve(); PA.preserve(); } diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll index 6227a5c822b107..9941d4c070d39a 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/basic.ll @@ -442,7 +442,7 @@ define i32 @switch_range(i32 %cond) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[S:%.*]] = urem i32 [[COND:%.*]], 3 ; CHECK-NEXT: [[S1:%.*]] = add nuw nsw i32 [[S]], 1 -; CHECK-NEXT: switch i32 [[S1]], label [[UNREACHABLE:%.*]] [ +; CHECK-NEXT: switch i32 [[S1]], label [[DEFAULT_UNREACHABLE:%.*]] [ ; CHECK-NEXT: i32 1, label [[EXIT1:%.*]] ; CHECK-NEXT: i32 2, label [[EXIT2:%.*]] ; CHECK-NEXT: i32 3, label [[EXIT1]] @@ -451,6 +451,8 @@ define i32 @switch_range(i32 %cond) { ; CHECK-NEXT: ret i32 1 ; CHECK: exit2: ; CHECK-NEXT: ret i32 2 +; CHECK: default.unreachable: +; CHECK-NEXT: unreachable ; CHECK: unreachable: ; CHECK-NEXT: ret i32 0 ; @@ -513,10 +515,9 @@ define i8 @switch_defaultdest_multipleuse(i8 %t0) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[O:%.*]] = or i8 [[T0:%.*]], 1 ; CHECK-NEXT: [[R:%.*]] = srem i8 1, [[O]] -; CHECK-NEXT: switch i8 [[R]], label [[EXIT:%.*]] [ -; CHECK-NEXT: i8 0, label [[EXIT]] -; CHECK-NEXT: i8 1, label [[EXIT]] -; CHECK-NEXT: ] +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: default.unreachable: +; CHECK-NEXT: unreachable ; CHECK: exit: ; CHECK-NEXT: ret i8 0 ; diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll b/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll index 1c3c818951a632..4d396b54224011 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll @@ -8,7 +8,7 @@ define i32 @test_unreachable_default(i32 noundef %num) { ; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2 -; CHECK-NEXT: switch i32 [[COND]], label [[SW_DEFAULT:%.*]] [ +; CHECK-NEXT: switch i32 [[COND]], label [[DEFAULT_UNREACHABLE:%.*]] [ ; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] ; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] ; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] @@ -22,11 +22,13 @@ define i32 @test_unreachable_default(i32 noundef %num) { ; CHECK: sw.bb4: ; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() ; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: default.unreachable: +; CHECK-NEXT: unreachable ; CHECK: sw.default: ; CHECK-NEXT: [[CALL6:%.*]] = call i32 @call3() ; CHECK-NEXT: br label [[CLEANUP]] ; CHECK: cleanup: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL6]], [[SW_DEFAULT]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] +; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL6]], [[SW_DEFAULT:%.*]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] ; CHECK-NEXT: ret i32 [[RETVAL_0]] ; entry: @@ -67,10 +69,10 @@ define i32 @test_unreachable_default_shared_edge(i32 noundef %num) { ; CHECK-NEXT: [[SUB:%.*]] = add i32 [[NUM]], -120 ; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[SUB]], 3 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 2 -; CHECK-NEXT: switch i32 [[COND]], label [[SW_BB4:%.*]] [ +; CHECK-NEXT: switch i32 [[COND]], label [[DEFAULT_UNREACHABLE:%.*]] [ ; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] ; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] -; CHECK-NEXT: i32 2, label [[SW_BB4]] +; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] ; CHECK-NEXT: ] ; CHECK: sw.bb: ; CHECK-NEXT: [[CALL:%.*]] = call i32 @call0() @@ -78,6 +80,8 @@ define i32 @test_unreachable_default_shared_edge(i32 noundef %num) { ; CHECK: sw.bb2: ; CHECK-NEXT: [[CALL3:%.*]] = call i32 @call1() ; CHECK-NEXT: br label [[CLEANUP]] +; CHECK: default.unreachable: +; CHECK-NEXT: unreachable ; CHECK: sw.bb4: ; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() ; CHECK-NEXT: br label [[CLEANUP]] From f6fedc97acd6d0c1226e9717dfdf0335dae733b8 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Tue, 30 Jan 2024 23:56:32 +0800 Subject: [PATCH 3/5] fixup! [CVP] Check whether the default case is reachable --- .../Scalar/CorrelatedValuePropagation.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index e1a5d83e4b96c2..0a3ddcbeaa16e3 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -412,7 +412,8 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI, } BasicBlock *DefaultDest = SI->getDefaultDest(); - if (!isa(DefaultDest->getFirstNonPHIOrDbg())) { + if (ReachableCaseCount > 1 && + !isa(DefaultDest->getFirstNonPHIOrDbg())) { ConstantRange CR = LVI->getConstantRangeAtUse(I->getOperandUse(0), /*UndefAllowed*/ false); // The default dest is unreachable if all cases are covered. @@ -422,17 +423,12 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI, BB->getParent(), DefaultDest); new UnreachableInst(BB->getContext(), NewUnreachableBB); - bool RemoveOldBB = --SuccessorsCount[DefaultDest] == 0; - - if (RemoveOldBB) - DefaultDest->removePredecessor(BB); + DefaultDest->removePredecessor(BB); SI->setDefaultDest(NewUnreachableBB); - if (RemoveOldBB) - DTU.applyUpdatesPermissive( - {{DominatorTree::Delete, BB, DefaultDest}}); DTU.applyUpdatesPermissive( - {{DominatorTree::Insert, BB, NewUnreachableBB}}); + {{DominatorTree::Delete, BB, DefaultDest}, + {DominatorTree::Insert, BB, NewUnreachableBB}}); ++NumDeadCases; Changed = true; @@ -1257,7 +1253,12 @@ CorrelatedValuePropagationPass::run(Function &F, FunctionAnalysisManager &AM) { if (!Changed) { PA = PreservedAnalyses::all(); } else { - assert(DT->verify()); +#if defined(EXPENSIVE_CHECKS) + assert(DT->verify(DominatorTree::VerificationLevel::Full)); +#else + assert(DT->verify(DominatorTree::VerificationLevel::Fast)); +#endif // EXPENSIVE_CHECKS + PA.preserve(); PA.preserve(); } From 53b8e4e987795a363980697605fdea64835d7786 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 31 Jan 2024 00:25:40 +0800 Subject: [PATCH 4/5] fixup! [CVP] Check whether the default case is reachable --- llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index 0a3ddcbeaa16e3..24e1677bf64342 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -426,9 +426,11 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI, DefaultDest->removePredecessor(BB); SI->setDefaultDest(NewUnreachableBB); + if (SuccessorsCount[DefaultDest] == 1) + DTU.applyUpdatesPermissive( + {{DominatorTree::Delete, BB, DefaultDest}}); DTU.applyUpdatesPermissive( - {{DominatorTree::Delete, BB, DefaultDest}, - {DominatorTree::Insert, BB, NewUnreachableBB}}); + {{DominatorTree::Insert, BB, NewUnreachableBB}}); ++NumDeadCases; Changed = true; From f117f38acd109273c705d8467560cba877d9ce4a Mon Sep 17 00:00:00 2001 From: Yingwei Zheng Date: Wed, 31 Jan 2024 01:12:13 +0800 Subject: [PATCH 5/5] [CVP] Add a phi node to the shared dest BB. NFC. --- llvm/test/Transforms/CorrelatedValuePropagation/switch.ll | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll b/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll index 4d396b54224011..a0794d5efe9320 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/switch.ll @@ -83,7 +83,7 @@ define i32 @test_unreachable_default_shared_edge(i32 noundef %num) { ; CHECK: default.unreachable: ; CHECK-NEXT: unreachable ; CHECK: sw.bb4: -; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call2() +; CHECK-NEXT: [[CALL5:%.*]] = call i32 @call4(i32 [[SUB]]) ; CHECK-NEXT: br label [[CLEANUP]] ; CHECK: cleanup: ; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ] @@ -108,7 +108,8 @@ sw.bb2: br label %cleanup sw.bb4: - %call5 = call i32 @call2() + %val = phi i32 [ %sub, %entry ], [ %sub, %entry ] + %call5 = call i32 @call4(i32 %val) br label %cleanup cleanup: @@ -297,3 +298,4 @@ declare i32 @call0() declare i32 @call1() declare i32 @call2() declare i32 @call3() +declare i32 @call4(i32)