[llvm] [SimplifyCFG] Convert switch to cmp/select sequence (PR #82795)
Acim Maravic via llvm-commits
llvm-commits at lists.llvm.org
Thu May 23 05:19:20 PDT 2024
https://github.com/Acim-Maravic updated https://github.com/llvm/llvm-project/pull/82795
>From 1e3146f488e15ddac5eced2a54ee5f5df7ae4c96 Mon Sep 17 00:00:00 2001
From: Acim Maravic <acim.maravic at syrmia.com>
Date: Thu, 23 May 2024 13:52:37 +0200
Subject: [PATCH 1/2] [NFC][SimplifyCFG] Convert switch to cmp/select sequence
Added tests that will show changes
---
.../SimplifyCFG/switch-to-select.ll | 319 ++++++++++++++++++
1 file changed, 319 insertions(+)
create mode 100644 llvm/test/Transforms/SimplifyCFG/switch-to-select.ll
diff --git a/llvm/test/Transforms/SimplifyCFG/switch-to-select.ll b/llvm/test/Transforms/SimplifyCFG/switch-to-select.ll
new file mode 100644
index 0000000000000..c431d18b072f9
--- /dev/null
+++ b/llvm/test/Transforms/SimplifyCFG/switch-to-select.ll
@@ -0,0 +1,319 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -passes=simplifycfg < %s | FileCheck -check-prefix=ALL %s
+
+define float @constant_single_PHInode(i32 %a, i32 %b, float %c, float %d) {
+; ALL-LABEL: @constant_single_PHInode(
+; ALL-NEXT: .entry:
+; ALL-NEXT: [[TMP0:%.*]] = icmp eq i32 [[A:%.*]], 1
+; ALL-NEXT: br i1 [[TMP0]], label [[SW:%.*]], label [[RETURN:%.*]]
+; ALL: sw:
+; ALL-NEXT: [[SCALE_I0:%.*]] = fmul reassoc nnan nsz arcp contract afn float [[C:%.*]], 2.000000e+00
+; ALL-NEXT: [[DOTI0:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[SCALE_I0]], -1.000000e+00
+; ALL-NEXT: [[DOTI1:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[D:%.*]], -3.000000e+00
+; ALL-NEXT: switch i32 [[B:%.*]], label [[RETURN]] [
+; ALL-NEXT: i32 0, label [[SW_BB1:%.*]]
+; ALL-NEXT: i32 1, label [[SW_BB2:%.*]]
+; ALL-NEXT: i32 2, label [[SW_BB3:%.*]]
+; ALL-NEXT: i32 3, label [[SW_BB4:%.*]]
+; ALL-NEXT: ]
+; ALL: sw.bb1:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb2:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb3:
+; ALL-NEXT: [[TMP1:%.*]] = fneg reassoc nnan nsz arcp contract afn float [[DOTI0]]
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb4:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: return:
+; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ -5.000000e+00, [[SW_BB4]] ], [ -1.000000e+00, [[SW_BB3]] ], [ 7.000000e+00, [[SW_BB2]] ], [ 1.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: ret float [[SAMPLEPOS_1_I0]]
+;
+.entry:
+ %5 = icmp eq i32 %a, 1
+ br i1 %5, label %sw, label %return
+
+sw:
+ %scale.i0 = fmul reassoc nnan nsz arcp contract afn float %c, 2.000000e+00
+ %.i0 = fadd reassoc nnan nsz arcp contract afn float %scale.i0, -1.000000e+00
+ %.i1 = fadd reassoc nnan nsz arcp contract afn float %d, -3.000000e+00
+ switch i32 %b, label %return [
+ i32 0, label %sw.bb1
+ i32 1, label %sw.bb2
+ i32 2, label %sw.bb3
+ i32 3, label %sw.bb4
+ ]
+sw.bb1: ; preds = %sw
+ br label %return
+
+sw.bb2: ; preds = %sw
+ br label %return
+
+sw.bb3: ; preds = %sw
+ %18 = fneg reassoc nnan nsz arcp contract afn float %.i0
+ br label %return
+
+sw.bb4: ; preds = %sw
+ br label %return
+
+return: ; preds = %sw.bb1, %sw.bb2, %sw.bb3, %sw.bb4, %sw, %.entry
+ %samplePos.1.i0 = phi float [ 0.000000e+00, %.entry ], [ -5.000000e+00, %sw.bb4 ], [ -1.000000e+00, %sw.bb3 ], [ 7.000000e+00, %sw.bb2 ], [ 1.000000e+00, %sw.bb1 ], [ 4.000000e+00, %sw ]
+ ret float %samplePos.1.i0
+}
+
+
+define float @constant_multiple_PHInode(i32 %a, i32 %b, float %c, float %d) {
+; ALL-LABEL: @constant_multiple_PHInode(
+; ALL-NEXT: .entry:
+; ALL-NEXT: [[TMP0:%.*]] = icmp eq i32 [[A:%.*]], 1
+; ALL-NEXT: br i1 [[TMP0]], label [[SW:%.*]], label [[RETURN:%.*]]
+; ALL: sw:
+; ALL-NEXT: [[SCALE_I0:%.*]] = fmul reassoc nnan nsz arcp contract afn float [[C:%.*]], 2.000000e+00
+; ALL-NEXT: [[DOTI0:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[SCALE_I0]], -1.000000e+00
+; ALL-NEXT: [[DOTI1:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[D:%.*]], -3.000000e+00
+; ALL-NEXT: switch i32 [[B:%.*]], label [[RETURN]] [
+; ALL-NEXT: i32 0, label [[SW_BB1:%.*]]
+; ALL-NEXT: i32 1, label [[SW_BB2:%.*]]
+; ALL-NEXT: i32 2, label [[SW_BB3:%.*]]
+; ALL-NEXT: ]
+; ALL: sw.bb1:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb2:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb3:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: return:
+; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ 3.000000e+00, [[SW_BB3]] ], [ 2.000000e+00, [[SW_BB2]] ], [ 1.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I1:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ -3.000000e+00, [[SW_BB3]] ], [ -2.000000e+00, [[SW_BB2]] ], [ -1.000000e+00, [[SW_BB1]] ], [ -4.000000e+00, [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I2:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ -3.000000e+00, [[SW_BB3]] ], [ 2.000000e+00, [[SW_BB2]] ], [ -1.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: [[RETVAL1:%.*]] = fadd float [[SAMPLEPOS_1_I0]], [[SAMPLEPOS_1_I1]]
+; ALL-NEXT: [[RETVAL:%.*]] = fadd float [[RETVAL1]], [[SAMPLEPOS_1_I2]]
+; ALL-NEXT: ret float [[RETVAL]]
+;
+.entry:
+ %5 = icmp eq i32 %a, 1
+ br i1 %5, label %sw, label %return
+
+sw:
+ %scale.i0 = fmul reassoc nnan nsz arcp contract afn float %c, 2.000000e+00
+ %.i0 = fadd reassoc nnan nsz arcp contract afn float %scale.i0, -1.000000e+00
+ %.i1 = fadd reassoc nnan nsz arcp contract afn float %d, -3.000000e+00
+ switch i32 %b, label %return [
+ i32 0, label %sw.bb1
+ i32 1, label %sw.bb2
+ i32 2, label %sw.bb3
+ i32 3, label %sw.bb4
+ ]
+sw.bb1: ; preds = %sw
+ br label %return
+
+sw.bb2: ; preds = %sw
+ br label %return
+
+sw.bb3: ; preds = %sw
+ br label %return
+
+sw.bb4: ; preds = %sw
+ br label %return
+
+return: ; preds = %sw.bb1, %sw.bb2, %sw.bb3, %sw.bb4, %sw, %.entry
+ %samplePos.1.i0 = phi float [ 0.000000e+00, %.entry ], [ 4.000000e+00, %sw.bb4 ], [ 3.000000e+00, %sw.bb3 ], [ 2.000000e+00, %sw.bb2 ], [ 1.000000e+00, %sw.bb1 ], [ 4.000000e+00, %sw ]
+ %samplePos.1.i1 = phi float [ 0.000000e+00, %.entry ], [ -4.000000e+00, %sw.bb4 ], [ -3.000000e+00, %sw.bb3 ], [ -2.000000e+00, %sw.bb2 ], [ -1.000000e+00, %sw.bb1 ], [ -4.000000e+00, %sw ]
+ %samplePos.1.i2 = phi float [ 0.000000e+00, %.entry ], [ 4.000000e+00, %sw.bb4 ], [ -3.000000e+00, %sw.bb3 ], [ 2.000000e+00, %sw.bb2 ], [ -1.000000e+00, %sw.bb1 ], [ 4.000000e+00, %sw ]
+ %retVal1 = fadd float %samplePos.1.i0, %samplePos.1.i1
+ %retVal = fadd float %retVal1, %samplePos.1.i2
+ ret float %retVal
+}
+
+define float @partial_constant_single_PHInode(i32 %a, i32 %b, float %c, float %d) {
+; ALL-LABEL: @partial_constant_single_PHInode(
+; ALL-NEXT: .entry:
+; ALL-NEXT: [[TMP0:%.*]] = icmp eq i32 [[A:%.*]], 1
+; ALL-NEXT: br i1 [[TMP0]], label [[SW:%.*]], label [[RETURN:%.*]]
+; ALL: sw:
+; ALL-NEXT: [[SCALE_I0:%.*]] = fmul reassoc nnan nsz arcp contract afn float [[C:%.*]], 2.000000e+00
+; ALL-NEXT: [[DOTI0:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[SCALE_I0]], -1.000000e+00
+; ALL-NEXT: [[DOTI1:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[D:%.*]], -3.000000e+00
+; ALL-NEXT: switch i32 [[B:%.*]], label [[RETURN]] [
+; ALL-NEXT: i32 0, label [[SW_BB1:%.*]]
+; ALL-NEXT: i32 1, label [[SW_BB2:%.*]]
+; ALL-NEXT: i32 2, label [[SW_BB3:%.*]]
+; ALL-NEXT: i32 3, label [[SW_BB4:%.*]]
+; ALL-NEXT: ]
+; ALL: sw.bb1:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb2:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb3:
+; ALL-NEXT: [[TMP1:%.*]] = fneg reassoc nnan nsz arcp contract afn float [[DOTI0]]
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb4:
+; ALL-NEXT: [[TMP2:%.*]] = fneg reassoc nnan nsz arcp contract afn float [[DOTI0]]
+; ALL-NEXT: br label [[RETURN]]
+; ALL: return:
+; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ [[TMP2]], [[SW_BB4]] ], [ -1.000000e+00, [[SW_BB3]] ], [ [[DOTI0]], [[SW_BB2]] ], [ 1.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: ret float [[SAMPLEPOS_1_I0]]
+;
+.entry:
+ %5 = icmp eq i32 %a, 1
+ br i1 %5, label %sw, label %return
+
+sw:
+ %scale.i0 = fmul reassoc nnan nsz arcp contract afn float %c, 2.000000e+00
+ %.i0 = fadd reassoc nnan nsz arcp contract afn float %scale.i0, -1.000000e+00
+ %.i1 = fadd reassoc nnan nsz arcp contract afn float %d, -3.000000e+00
+ switch i32 %b, label %return [
+ i32 0, label %sw.bb1
+ i32 1, label %sw.bb2
+ i32 2, label %sw.bb3
+ i32 3, label %sw.bb4
+ ]
+sw.bb1: ; preds = %sw
+ br label %return
+
+sw.bb2: ; preds = %sw
+ br label %return
+
+sw.bb3: ; preds = %sw
+ %18 = fneg reassoc nnan nsz arcp contract afn float %.i0
+ br label %return
+
+sw.bb4: ; preds = %sw
+ %20 = fneg reassoc nnan nsz arcp contract afn float %.i0
+ br label %return
+return: ; preds = %sw.bb1, %sw.bb2, %sw.bb3, %sw.bb4, %sw, %.entry
+ %samplePos.1.i0 = phi float [ 0.000000e+00, %.entry ], [ %20, %sw.bb4 ], [ -1.000000e+00, %sw.bb3 ], [ %.i0, %sw.bb2 ], [ 1.000000e+00, %sw.bb1 ], [ 4.000000e+00, %sw ]
+ ret float %samplePos.1.i0
+}
+
+define float @partial_constant_multiple_PHInode(i32 %a, i32 %b, float %c, float %d) {
+; ALL-LABEL: @partial_constant_multiple_PHInode(
+; ALL-NEXT: .entry:
+; ALL-NEXT: [[TMP0:%.*]] = icmp eq i32 [[A:%.*]], 1
+; ALL-NEXT: br i1 [[TMP0]], label [[SW:%.*]], label [[RETURN:%.*]]
+; ALL: sw:
+; ALL-NEXT: [[SCALE_I0:%.*]] = fmul reassoc nnan nsz arcp contract afn float [[C:%.*]], 2.000000e+00
+; ALL-NEXT: [[DOTI0:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[SCALE_I0]], -1.000000e+00
+; ALL-NEXT: [[DOTI1:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[D:%.*]], -3.000000e+00
+; ALL-NEXT: switch i32 [[B:%.*]], label [[RETURN]] [
+; ALL-NEXT: i32 0, label [[SW_BB1:%.*]]
+; ALL-NEXT: i32 1, label [[SW_BB2:%.*]]
+; ALL-NEXT: i32 2, label [[SW_BB3:%.*]]
+; ALL-NEXT: i32 3, label [[SW_BB4:%.*]]
+; ALL-NEXT: ]
+; ALL: sw.bb1:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb2:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb3:
+; ALL-NEXT: [[TMP1:%.*]] = fneg reassoc nnan nsz arcp contract afn float [[DOTI0]]
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb4:
+; ALL-NEXT: [[TMP2:%.*]] = fneg reassoc nnan nsz arcp contract afn float [[DOTI0]]
+; ALL-NEXT: br label [[RETURN]]
+; ALL: return:
+; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ [[TMP2]], [[SW_BB4]] ], [ -1.000000e+00, [[SW_BB3]] ], [ [[DOTI0]], [[SW_BB2]] ], [ 1.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I1:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ [[DOTI1]], [[SW_BB4]] ], [ [[DOTI1]], [[SW_BB3]] ], [ [[DOTI1]], [[SW_BB2]] ], [ 2.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I2:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ -1.000000e+00, [[SW_BB4]] ], [ [[TMP1]], [[SW_BB3]] ], [ 1.000000e+00, [[SW_BB2]] ], [ 3.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: [[RETVAL1:%.*]] = fadd float [[SAMPLEPOS_1_I0]], [[SAMPLEPOS_1_I1]]
+; ALL-NEXT: [[RETVAL:%.*]] = fadd float [[RETVAL1]], [[SAMPLEPOS_1_I2]]
+; ALL-NEXT: ret float [[RETVAL]]
+;
+.entry:
+ %5 = icmp eq i32 %a, 1
+ br i1 %5, label %sw, label %return
+
+sw:
+ %scale.i0 = fmul reassoc nnan nsz arcp contract afn float %c, 2.000000e+00
+ %.i0 = fadd reassoc nnan nsz arcp contract afn float %scale.i0, -1.000000e+00
+ %.i1 = fadd reassoc nnan nsz arcp contract afn float %d, -3.000000e+00
+ switch i32 %b, label %return [
+ i32 0, label %sw.bb1
+ i32 1, label %sw.bb2
+ i32 2, label %sw.bb3
+ i32 3, label %sw.bb4
+ ]
+sw.bb1: ; preds = %sw
+ br label %return
+
+sw.bb2: ; preds = %sw
+ br label %return
+
+sw.bb3: ; preds = %sw
+ %18 = fneg reassoc nnan nsz arcp contract afn float %.i0
+ br label %return
+
+sw.bb4: ; preds = %sw
+ %20 = fneg reassoc nnan nsz arcp contract afn float %.i0
+ br label %return
+return: ; preds = %sw.bb1, %sw.bb2, %sw.bb3, %sw.bb4, %sw, %.entry
+ %samplePos.1.i0 = phi float [ 0.000000e+00, %.entry ], [ %20, %sw.bb4 ], [ -1.000000e+00, %sw.bb3 ], [ %.i0, %sw.bb2 ], [ 1.000000e+00, %sw.bb1 ], [ 4.000000e+00, %sw ]
+ %samplePos.1.i1 = phi float [ 0.000000e+00, %.entry ], [ %.i1, %sw.bb4 ], [ %.i1, %sw.bb3 ], [ %.i1, %sw.bb2 ], [ 2.000000e+00, %sw.bb1 ], [ 4.000000e+00, %sw ]
+ %samplePos.1.i2 = phi float [ 0.000000e+00, %.entry ], [ -1.000000e+00, %sw.bb4 ], [ %18, %sw.bb3 ], [ 1.000000e+00, %sw.bb2 ], [ 3.000000e+00, %sw.bb1 ], [ 4.000000e+00, %sw ]
+ %retVal1 = fadd float %samplePos.1.i0, %samplePos.1.i1
+ %retVal = fadd float %retVal1, %samplePos.1.i2
+ ret float %retVal
+}
+
+define float @two_instructions_in_bb(i32 %a, i32 %b, float %c, float %d) {
+; ALL-LABEL: @two_instructions_in_bb(
+; ALL-NEXT: .entry:
+; ALL-NEXT: [[TMP0:%.*]] = icmp eq i32 [[A:%.*]], 1
+; ALL-NEXT: br i1 [[TMP0]], label [[SW:%.*]], label [[RETURN:%.*]]
+; ALL: sw:
+; ALL-NEXT: [[SCALE_I0:%.*]] = fmul reassoc nnan nsz arcp contract afn float [[C:%.*]], 2.000000e+00
+; ALL-NEXT: [[DOTI0:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[SCALE_I0]], -1.000000e+00
+; ALL-NEXT: [[DOTI1:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[D:%.*]], -3.000000e+00
+; ALL-NEXT: switch i32 [[B:%.*]], label [[RETURN]] [
+; ALL-NEXT: i32 0, label [[SW_BB1:%.*]]
+; ALL-NEXT: i32 1, label [[SW_BB2:%.*]]
+; ALL-NEXT: i32 2, label [[SW_BB3:%.*]]
+; ALL-NEXT: i32 3, label [[SW_BB4:%.*]]
+; ALL-NEXT: ]
+; ALL: sw.bb1:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb2:
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb3:
+; ALL-NEXT: [[TMP1:%.*]] = fneg reassoc nnan nsz arcp contract afn float [[DOTI0]]
+; ALL-NEXT: br label [[RETURN]]
+; ALL: sw.bb4:
+; ALL-NEXT: [[TMP2:%.*]] = fneg reassoc nnan nsz arcp contract afn float [[DOTI0]]
+; ALL-NEXT: [[TMP3:%.*]] = fneg reassoc nnan nsz arcp contract afn float [[DOTI1]]
+; ALL-NEXT: br label [[RETURN]]
+; ALL: return:
+; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ [[TMP2]], [[SW_BB4]] ], [ -1.000000e+00, [[SW_BB3]] ], [ [[DOTI0]], [[SW_BB2]] ], [ 1.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: ret float [[SAMPLEPOS_1_I0]]
+;
+.entry:
+ %5 = icmp eq i32 %a, 1
+ br i1 %5, label %sw, label %return
+
+sw:
+ %scale.i0 = fmul reassoc nnan nsz arcp contract afn float %c, 2.000000e+00
+ %.i0 = fadd reassoc nnan nsz arcp contract afn float %scale.i0, -1.000000e+00
+ %.i1 = fadd reassoc nnan nsz arcp contract afn float %d, -3.000000e+00
+ switch i32 %b, label %return [
+ i32 0, label %sw.bb1
+ i32 1, label %sw.bb2
+ i32 2, label %sw.bb3
+ i32 3, label %sw.bb4
+ ]
+sw.bb1: ; preds = %sw
+ br label %return
+
+sw.bb2: ; preds = %sw
+ br label %return
+
+sw.bb3: ; preds = %sw
+ %18 = fneg reassoc nnan nsz arcp contract afn float %.i0
+ br label %return
+
+sw.bb4: ; preds = %sw
+ %20 = fneg reassoc nnan nsz arcp contract afn float %.i0
+ %21 = fneg reassoc nnan nsz arcp contract afn float %.i1
+ br label %return
+return: ; preds = %sw.bb1, %sw.bb2, %sw.bb3, %sw.bb4, %sw, %.entry
+ %samplePos.1.i0 = phi float [ 0.000000e+00, %.entry ], [ %20, %sw.bb4 ], [ -1.000000e+00, %sw.bb3 ], [ %.i0, %sw.bb2 ], [ 1.000000e+00, %sw.bb1 ], [ 4.000000e+00, %sw ]
+ ret float %samplePos.1.i0
+}
>From 4b32267d0b52a0b44ffd62b6faaa72ab08a9940f Mon Sep 17 00:00:00 2001
From: Acim Maravic <acim.maravic at syrmia.com>
Date: Thu, 23 May 2024 14:15:49 +0200
Subject: [PATCH 2/2] [SimplifyCFG] Convert switch to cmp/select sequence
---
llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 283 ++++++++++++++++++
.../SimplifyCFG/switch-to-select.ll | 102 ++++---
2 files changed, 345 insertions(+), 40 deletions(-)
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 93701b2a77916..808f590267529 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6171,6 +6171,286 @@ static bool trySwitchToSelect(SwitchInst *SI, IRBuilder<> &Builder,
return true;
}
+// The first field contains the value that the switch produces when a certain
+// case group is selected, and the second field is a vector containing the
+// cases composing the case group.
+using SwitchCaseResultVectorTy2 = SmallVector<std::pair<Value *, SmallVector<Value *, 4>>, 2>;
+
+// The first field contains the phi node that generates a result of the switch
+// and the second field contains the value generated for a certain case in the
+// switch for that PHI.
+using SwitchCaseResultsTy2 = SmallVector<std::pair<PHINode *, Value *>, 4>;
+
+using PHINodeToCaseEntryValueMapTy = std::map<PHINode *, SmallVector<std::pair<ConstantInt *, Value *>, 4>>;
+
+// Helper function that will return true if there is Default Value for each PHI
+bool allPHINodesHaveDefaultValue(const SwitchCaseResultsTy2& Results) {
+ for (const auto& Pair : Results)
+ if (Pair.second == nullptr)
+ return false;
+ return true;
+}
+
+//Helper function that will return true if there is no space for
+// optimization
+bool isUnableToOptimize(PHINodeToCaseEntryValueMapTy &Map) {
+ for (const auto &Entry : Map) {
+ for (const auto &ValuePair : Entry.second) {
+ if (isa<Constant>(ValuePair.second))
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool getCaseResultsWithoutConstants(SwitchInst *SI, BasicBlock *CaseDest, BasicBlock **CommonDest, SmallVectorImpl<std::pair<PHINode *, Value *>> &Res, bool IsDefault = false) {
+
+ BasicBlock *Pred = SI->getParent();
+ // Pred ->dump();
+ int NumOfInsts = 0;
+
+ /// Check if there is only one instruction per block, except from default block
+ if (!IsDefault) {
+
+ for (Instruction &I : CaseDest->instructionsWithoutDebug(false)) {
+
+ if (I.isTerminator()) {
+ // If the terminator is a simple branch, continue to the next block.
+ if (I.getNumSuccessors() != 1 || I.isSpecialTerminator())
+ return false;
+
+ Pred = CaseDest;
+ CaseDest = I.getSuccessor(0);
+ } else {
+ // if there is more then one instruction in the block, we can not process that case
+ if (++NumOfInsts > 1)
+ return false;
+
+ for (auto &Use : I.uses()) {
+ User *User = Use.getUser();
+
+ if (Instruction *I = dyn_cast<Instruction>(User))
+ if (I->getParent() == CaseDest)
+ continue;
+
+ if (PHINode *Phi = dyn_cast<PHINode>(User))
+ if (Phi->getIncomingBlock(Use) == CaseDest)
+ continue;
+
+ return false;
+ }
+ }
+ }
+ }
+
+ // If we did not have a CommonDest before, use the current one.
+ if (!*CommonDest)
+ *CommonDest = CaseDest;
+ // If the destination isn't the common one, abort.
+ if (CaseDest != *CommonDest)
+ return false;
+
+ // Get the values for this case from phi nodes in the destination block.
+ for (PHINode &PHI : (*CommonDest)->phis()) {
+ int Idx = PHI.getBasicBlockIndex(Pred);
+ if (Idx == -1)
+ continue;
+
+ Value *Val = PHI.getIncomingValue(Idx);
+
+ if (!Val)
+ return false;
+
+ Res.push_back(std::make_pair(&PHI, Val));
+ }
+ return !Res.empty();
+}
+
+// Helper function that fills in map, that for each PHI Node has pair CaseValue-ReturnValue
+static void mapCaseToResultWithMap(SwitchCaseResultsTy2 &Results, PHINodeToCaseEntryValueMapTy &Map, ConstantInt *CaseVal, SwitchCaseResultVectorTy2 &UniqueResults, Value *Result) {
+ // fill in PHINodeToCaseEntryValueMapTy &Map
+ for (const auto &Pair : Results) {
+ PHINode *PHI = Pair.first;
+ Value *ReturnValue = Pair.second;
+ Map[PHI].emplace_back(std::make_pair(CaseVal, ReturnValue));
+ }
+
+ // fill in SwitchCaseResultVectorTy2 &UniqueResults
+ for (auto &I : UniqueResults) {
+ if (I.first == Result) {
+ I.second.push_back(CaseVal);
+ return;
+ }
+ }
+ UniqueResults.push_back({Result, SmallVector<Value *, 4>{1, CaseVal}});
+
+}
+
+static bool initializeUniqueCasesWithoutConstants(SwitchInst *SI, BasicBlock *&CommonDest, PHINodeToCaseEntryValueMapTy &Map, SwitchCaseResultVectorTy2 &UniqueResults, PHINode *&PHI, SwitchCaseResultsTy2 &DefaultResults) {
+
+ for (const auto &Case : SI->cases()) {
+ SwitchCaseResultsTy2 Results;
+ ConstantInt *CaseVal = Case.getCaseValue();
+ if(!getCaseResultsWithoutConstants(SI, Case.getCaseSuccessor(), &CommonDest, Results))
+ return false;
+
+ mapCaseToResultWithMap(Results, Map, CaseVal, UniqueResults,Results.begin()->second);
+
+ // Check the PHI consistency.
+ if (!PHI)
+ PHI = Results[0].first;
+ else if (PHI != Results[0].first)
+ return false;
+ }
+
+ BasicBlock *DefaultDest = SI->getDefaultDest();
+
+ if (!getCaseResultsWithoutConstants(SI, DefaultDest, &CommonDest, DefaultResults, true))
+ return false;
+
+ if (!allPHINodesHaveDefaultValue(DefaultResults) && !isa<UnreachableInst>(DefaultDest->getFirstNonPHIOrDbg()))
+ return false;
+
+ return true;
+}
+
+Value *createSelectChain(Value *Condition, Value *DefaultResult,
+ const SwitchCaseResultVectorTy2 &ResultVector,
+ unsigned StartIndex, PHINode *PHI, SwitchInst *SI,
+ IRBuilder<> &Builder, DomTreeUpdater *DTU) {
+
+ if (StartIndex >= ResultVector.size() && DefaultResult)
+ return DefaultResult;
+
+ if (StartIndex >= ResultVector.size() && !DefaultResult)
+ return nullptr;
+
+ Value *CurrentCase = ResultVector[StartIndex].second[0];
+ // check if the ReturnValue is a constant
+ if (Constant *C = dyn_cast<Constant>(ResultVector[StartIndex].first)) {
+ Value *ValueCompare =
+ Builder.CreateICmpEQ(Condition, CurrentCase, "switch.selectcmp");
+ Value *NextSelect =
+ createSelectChain(Condition, DefaultResult, ResultVector,
+ StartIndex + 1, PHI, SI, Builder, DTU);
+ Value *SelectedValue =
+ Builder.CreateSelect(ValueCompare, ResultVector[StartIndex].first,
+ NextSelect, "switch.select");
+
+ if (DTU) {
+ DTU->applyUpdates(
+ {{DominatorTree::Delete, SI->getParent(), SI->getDefaultDest()}});
+ }
+
+ return SelectedValue;
+
+ }
+ // Move to the next case if CurrentCase is not a constant
+ return createSelectChain(Condition, DefaultResult, ResultVector,
+ StartIndex + 1, PHI, SI, Builder, DTU);
+}
+
+static Value *foldSwitchToSelect2(const SwitchCaseResultVectorTy2 &ResultVector,
+ Value *DefaultResult, Value *Condition,
+ PHINode *&PHI, SwitchInst *SI,
+ IRBuilder<> &Builder, DomTreeUpdater *DTU) {
+ if (ResultVector.size() > 2) {
+ Value *FinalSelect = createSelectChain(
+ Condition, DefaultResult, ResultVector, 0, PHI, SI, Builder, DTU);
+
+ if (FinalSelect)
+ return FinalSelect;
+ }
+
+ return nullptr;
+}
+
+/// Helper function that will try to convert switch to cmp/select sequence
+static bool convertSwitchToCmpAndSelect(SwitchInst *SI, IRBuilder<> &Builder,
+ DomTreeUpdater *DTU,
+ const DataLayout &DL,
+ const TargetTransformInfo &TTI) {
+
+ BasicBlock *CommonDest = nullptr;
+ PHINodeToCaseEntryValueMapTy Map;
+ SwitchCaseResultVectorTy2 UniqueResults;
+ PHINode *PHI = nullptr;
+ SwitchCaseResultsTy2 DefaultResults;
+
+ if (!initializeUniqueCasesWithoutConstants(SI, CommonDest, Map, UniqueResults, PHI, DefaultResults))
+ return false;
+
+ if (isUnableToOptimize(Map))
+ return false;
+
+ // for each PHI, call function foldSwitchToSelect
+ for (const auto &Entry : Map) {
+ PHI = Entry.first;
+ SwitchCaseResultVectorTy2 ResultVector;
+
+ // For each PHi fill in ResultVector
+ for (const auto &ValuePair : Entry.second) {
+ ConstantInt *CaseVal = ValuePair.first;
+ Value *ReturnValue = ValuePair.second;
+ ResultVector.push_back(
+ std::make_pair(ReturnValue, SmallVector<Value *, 4>(1, CaseVal)));
+ }
+
+ // For each PHI we need Default Result
+ Value *DefaultResult = nullptr;
+ for (const auto &ValuePair : DefaultResults) {
+ if (PHI == ValuePair.first)
+ DefaultResult = ValuePair.second;
+ }
+
+ assert(PHI != nullptr && "PHI for value select not found");
+ assert(DefaultResult != nullptr && "Default value for switch not found");
+
+ Value *SelectValue = foldSwitchToSelect2(ResultVector, DefaultResult, SI->getCondition(), PHI, SI, Builder,DTU);
+
+ if (!SelectValue)
+ return false;
+
+ int Index = PHI->getBasicBlockIndex(SI->getParent());
+ if (Index != -1) {
+ PHI->setIncomingValue(Index, SelectValue);
+ }
+
+ for (auto Case = SI->case_begin(); Case != SI->case_end(); ++Case) {
+ int Index = PHI->getBasicBlockIndex(Case->getCaseSuccessor());
+ if (Index != -1) {
+ Value *Val = PHI->getIncomingValue(Index);
+ if (isa<Constant>(Val)) {
+ PHI->setIncomingValue(Index, SelectValue);
+ }
+ }
+ }
+ }
+
+ for (auto Case = SI->case_begin(); Case != SI->case_end(); ++Case) {
+ ConstantInt *CaseVal = Case->getCaseValue();
+ bool IsSafeToRemove = true;
+ for (const auto &Entry : Map) {
+ for (const auto &ValuePair : Entry.second) {
+ ConstantInt *constantInt = ValuePair.first;
+ Value *value = ValuePair.second;
+ if (constantInt == CaseVal)
+ if (!isa<Constant>(value)) {
+ IsSafeToRemove = false;
+ break;
+ }
+ }
+ }
+
+ if (IsSafeToRemove) {
+ SI->removeCase(Case);
+ break;
+ }
+
+ }
+ return true;
+}
+
namespace {
/// This class represents a lookup table that can be used to replace a switch.
@@ -7124,6 +7404,9 @@ bool SimplifyCFGOpt::simplifySwitch(SwitchInst *SI, IRBuilder<> &Builder) {
SwitchToLookupTable(SI, Builder, DTU, DL, TTI))
return requestResimplify();
+ if (convertSwitchToCmpAndSelect(SI, Builder, DTU, DL, TTI))
+ return requestResimplify();
+
if (simplifySwitchOfPowersOfTwo(SI, Builder, DL, TTI))
return requestResimplify();
diff --git a/llvm/test/Transforms/SimplifyCFG/switch-to-select.ll b/llvm/test/Transforms/SimplifyCFG/switch-to-select.ll
index c431d18b072f9..a76f0fd2269ba 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch-to-select.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch-to-select.ll
@@ -10,23 +10,21 @@ define float @constant_single_PHInode(i32 %a, i32 %b, float %c, float %d) {
; ALL-NEXT: [[SCALE_I0:%.*]] = fmul reassoc nnan nsz arcp contract afn float [[C:%.*]], 2.000000e+00
; ALL-NEXT: [[DOTI0:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[SCALE_I0]], -1.000000e+00
; ALL-NEXT: [[DOTI1:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[D:%.*]], -3.000000e+00
-; ALL-NEXT: switch i32 [[B:%.*]], label [[RETURN]] [
-; ALL-NEXT: i32 0, label [[SW_BB1:%.*]]
-; ALL-NEXT: i32 1, label [[SW_BB2:%.*]]
-; ALL-NEXT: i32 2, label [[SW_BB3:%.*]]
-; ALL-NEXT: i32 3, label [[SW_BB4:%.*]]
-; ALL-NEXT: ]
-; ALL: sw.bb1:
-; ALL-NEXT: br label [[RETURN]]
-; ALL: sw.bb2:
-; ALL-NEXT: br label [[RETURN]]
+; ALL-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[B:%.*]], 0
+; ALL-NEXT: [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 [[B]], 1
+; ALL-NEXT: [[SWITCH_SELECTCMP2:%.*]] = icmp eq i32 [[B]], 2
+; ALL-NEXT: [[SWITCH_SELECTCMP3:%.*]] = icmp eq i32 [[B]], 3
+; ALL-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP3]], float -5.000000e+00, float 4.000000e+00
+; ALL-NEXT: [[SWITCH_SELECT4:%.*]] = select i1 [[SWITCH_SELECTCMP2]], float -1.000000e+00, float [[SWITCH_SELECT]]
+; ALL-NEXT: [[SWITCH_SELECT5:%.*]] = select i1 [[SWITCH_SELECTCMP1]], float 7.000000e+00, float [[SWITCH_SELECT4]]
+; ALL-NEXT: [[SWITCH_SELECT6:%.*]] = select i1 [[SWITCH_SELECTCMP]], float 1.000000e+00, float [[SWITCH_SELECT5]]
+; ALL-NEXT: [[COND:%.*]] = icmp eq i32 [[B]], 2
+; ALL-NEXT: br i1 [[COND]], label [[SW_BB3:%.*]], label [[RETURN]]
; ALL: sw.bb3:
; ALL-NEXT: [[TMP1:%.*]] = fneg reassoc nnan nsz arcp contract afn float [[DOTI0]]
; ALL-NEXT: br label [[RETURN]]
-; ALL: sw.bb4:
-; ALL-NEXT: br label [[RETURN]]
; ALL: return:
-; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ -5.000000e+00, [[SW_BB4]] ], [ -1.000000e+00, [[SW_BB3]] ], [ 7.000000e+00, [[SW_BB2]] ], [ 1.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ [[SWITCH_SELECT6]], [[SW_BB3]] ], [ [[SWITCH_SELECT6]], [[SW]] ]
; ALL-NEXT: ret float [[SAMPLEPOS_1_I0]]
;
.entry:
@@ -71,21 +69,35 @@ define float @constant_multiple_PHInode(i32 %a, i32 %b, float %c, float %d) {
; ALL-NEXT: [[SCALE_I0:%.*]] = fmul reassoc nnan nsz arcp contract afn float [[C:%.*]], 2.000000e+00
; ALL-NEXT: [[DOTI0:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[SCALE_I0]], -1.000000e+00
; ALL-NEXT: [[DOTI1:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[D:%.*]], -3.000000e+00
-; ALL-NEXT: switch i32 [[B:%.*]], label [[RETURN]] [
-; ALL-NEXT: i32 0, label [[SW_BB1:%.*]]
-; ALL-NEXT: i32 1, label [[SW_BB2:%.*]]
-; ALL-NEXT: i32 2, label [[SW_BB3:%.*]]
-; ALL-NEXT: ]
-; ALL: sw.bb1:
-; ALL-NEXT: br label [[RETURN]]
-; ALL: sw.bb2:
-; ALL-NEXT: br label [[RETURN]]
-; ALL: sw.bb3:
+; ALL-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[B:%.*]], 0
+; ALL-NEXT: [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 [[B]], 1
+; ALL-NEXT: [[SWITCH_SELECTCMP2:%.*]] = icmp eq i32 [[B]], 2
+; ALL-NEXT: [[SWITCH_SELECTCMP3:%.*]] = icmp eq i32 [[B]], 3
+; ALL-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP3]], float 4.000000e+00, float 4.000000e+00
+; ALL-NEXT: [[SWITCH_SELECT4:%.*]] = select i1 [[SWITCH_SELECTCMP2]], float -3.000000e+00, float [[SWITCH_SELECT]]
+; ALL-NEXT: [[SWITCH_SELECT5:%.*]] = select i1 [[SWITCH_SELECTCMP1]], float 2.000000e+00, float [[SWITCH_SELECT4]]
+; ALL-NEXT: [[SWITCH_SELECT6:%.*]] = select i1 [[SWITCH_SELECTCMP]], float -1.000000e+00, float [[SWITCH_SELECT5]]
+; ALL-NEXT: [[SWITCH_SELECTCMP7:%.*]] = icmp eq i32 [[B]], 0
+; ALL-NEXT: [[SWITCH_SELECTCMP8:%.*]] = icmp eq i32 [[B]], 1
+; ALL-NEXT: [[SWITCH_SELECTCMP9:%.*]] = icmp eq i32 [[B]], 2
+; ALL-NEXT: [[SWITCH_SELECTCMP10:%.*]] = icmp eq i32 [[B]], 3
+; ALL-NEXT: [[SWITCH_SELECT11:%.*]] = select i1 [[SWITCH_SELECTCMP10]], float 4.000000e+00, float 4.000000e+00
+; ALL-NEXT: [[SWITCH_SELECT12:%.*]] = select i1 [[SWITCH_SELECTCMP9]], float 3.000000e+00, float [[SWITCH_SELECT11]]
+; ALL-NEXT: [[SWITCH_SELECT13:%.*]] = select i1 [[SWITCH_SELECTCMP8]], float 2.000000e+00, float [[SWITCH_SELECT12]]
+; ALL-NEXT: [[SWITCH_SELECT14:%.*]] = select i1 [[SWITCH_SELECTCMP7]], float 1.000000e+00, float [[SWITCH_SELECT13]]
+; ALL-NEXT: [[SWITCH_SELECTCMP15:%.*]] = icmp eq i32 [[B]], 0
+; ALL-NEXT: [[SWITCH_SELECTCMP16:%.*]] = icmp eq i32 [[B]], 1
+; ALL-NEXT: [[SWITCH_SELECTCMP17:%.*]] = icmp eq i32 [[B]], 2
+; ALL-NEXT: [[SWITCH_SELECTCMP18:%.*]] = icmp eq i32 [[B]], 3
+; ALL-NEXT: [[SWITCH_SELECT19:%.*]] = select i1 [[SWITCH_SELECTCMP18]], float -4.000000e+00, float -4.000000e+00
+; ALL-NEXT: [[SWITCH_SELECT20:%.*]] = select i1 [[SWITCH_SELECTCMP17]], float -3.000000e+00, float [[SWITCH_SELECT19]]
+; ALL-NEXT: [[SWITCH_SELECT21:%.*]] = select i1 [[SWITCH_SELECTCMP16]], float -2.000000e+00, float [[SWITCH_SELECT20]]
+; ALL-NEXT: [[SWITCH_SELECT22:%.*]] = select i1 [[SWITCH_SELECTCMP15]], float -1.000000e+00, float [[SWITCH_SELECT21]]
; ALL-NEXT: br label [[RETURN]]
; ALL: return:
-; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ 3.000000e+00, [[SW_BB3]] ], [ 2.000000e+00, [[SW_BB2]] ], [ 1.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
-; ALL-NEXT: [[SAMPLEPOS_1_I1:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ -3.000000e+00, [[SW_BB3]] ], [ -2.000000e+00, [[SW_BB2]] ], [ -1.000000e+00, [[SW_BB1]] ], [ -4.000000e+00, [[SW]] ]
-; ALL-NEXT: [[SAMPLEPOS_1_I2:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ -3.000000e+00, [[SW_BB3]] ], [ 2.000000e+00, [[SW_BB2]] ], [ -1.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ [[SWITCH_SELECT14]], [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I1:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ [[SWITCH_SELECT22]], [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I2:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ [[SWITCH_SELECT6]], [[SW]] ]
; ALL-NEXT: [[RETVAL1:%.*]] = fadd float [[SAMPLEPOS_1_I0]], [[SAMPLEPOS_1_I1]]
; ALL-NEXT: [[RETVAL:%.*]] = fadd float [[RETVAL1]], [[SAMPLEPOS_1_I2]]
; ALL-NEXT: ret float [[RETVAL]]
@@ -134,14 +146,15 @@ define float @partial_constant_single_PHInode(i32 %a, i32 %b, float %c, float %d
; ALL-NEXT: [[SCALE_I0:%.*]] = fmul reassoc nnan nsz arcp contract afn float [[C:%.*]], 2.000000e+00
; ALL-NEXT: [[DOTI0:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[SCALE_I0]], -1.000000e+00
; ALL-NEXT: [[DOTI1:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[D:%.*]], -3.000000e+00
-; ALL-NEXT: switch i32 [[B:%.*]], label [[RETURN]] [
-; ALL-NEXT: i32 0, label [[SW_BB1:%.*]]
+; ALL-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[B:%.*]], 0
+; ALL-NEXT: [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 [[B]], 2
+; ALL-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP1]], float -1.000000e+00, float 4.000000e+00
+; ALL-NEXT: [[SWITCH_SELECT2:%.*]] = select i1 [[SWITCH_SELECTCMP]], float 1.000000e+00, float [[SWITCH_SELECT]]
+; ALL-NEXT: switch i32 [[B]], label [[RETURN]] [
+; ALL-NEXT: i32 3, label [[SW_BB4:%.*]]
; ALL-NEXT: i32 1, label [[SW_BB2:%.*]]
; ALL-NEXT: i32 2, label [[SW_BB3:%.*]]
-; ALL-NEXT: i32 3, label [[SW_BB4:%.*]]
; ALL-NEXT: ]
-; ALL: sw.bb1:
-; ALL-NEXT: br label [[RETURN]]
; ALL: sw.bb2:
; ALL-NEXT: br label [[RETURN]]
; ALL: sw.bb3:
@@ -151,7 +164,7 @@ define float @partial_constant_single_PHInode(i32 %a, i32 %b, float %c, float %d
; ALL-NEXT: [[TMP2:%.*]] = fneg reassoc nnan nsz arcp contract afn float [[DOTI0]]
; ALL-NEXT: br label [[RETURN]]
; ALL: return:
-; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ [[TMP2]], [[SW_BB4]] ], [ -1.000000e+00, [[SW_BB3]] ], [ [[DOTI0]], [[SW_BB2]] ], [ 1.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ [[TMP2]], [[SW_BB4]] ], [ [[SWITCH_SELECT2]], [[SW_BB3]] ], [ [[DOTI0]], [[SW_BB2]] ], [ [[SWITCH_SELECT2]], [[SW]] ]
; ALL-NEXT: ret float [[SAMPLEPOS_1_I0]]
;
.entry:
@@ -195,14 +208,23 @@ define float @partial_constant_multiple_PHInode(i32 %a, i32 %b, float %c, float
; ALL-NEXT: [[SCALE_I0:%.*]] = fmul reassoc nnan nsz arcp contract afn float [[C:%.*]], 2.000000e+00
; ALL-NEXT: [[DOTI0:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[SCALE_I0]], -1.000000e+00
; ALL-NEXT: [[DOTI1:%.*]] = fadd reassoc nnan nsz arcp contract afn float [[D:%.*]], -3.000000e+00
-; ALL-NEXT: switch i32 [[B:%.*]], label [[RETURN]] [
-; ALL-NEXT: i32 0, label [[SW_BB1:%.*]]
+; ALL-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[B:%.*]], 0
+; ALL-NEXT: [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 [[B]], 1
+; ALL-NEXT: [[SWITCH_SELECTCMP2:%.*]] = icmp eq i32 [[B]], 3
+; ALL-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP2]], float -1.000000e+00, float 4.000000e+00
+; ALL-NEXT: [[SWITCH_SELECT3:%.*]] = select i1 [[SWITCH_SELECTCMP1]], float 1.000000e+00, float [[SWITCH_SELECT]]
+; ALL-NEXT: [[SWITCH_SELECT4:%.*]] = select i1 [[SWITCH_SELECTCMP]], float 3.000000e+00, float [[SWITCH_SELECT3]]
+; ALL-NEXT: [[SWITCH_SELECTCMP5:%.*]] = icmp eq i32 [[B]], 0
+; ALL-NEXT: [[SWITCH_SELECTCMP6:%.*]] = icmp eq i32 [[B]], 2
+; ALL-NEXT: [[SWITCH_SELECT7:%.*]] = select i1 [[SWITCH_SELECTCMP6]], float -1.000000e+00, float 4.000000e+00
+; ALL-NEXT: [[SWITCH_SELECT8:%.*]] = select i1 [[SWITCH_SELECTCMP5]], float 1.000000e+00, float [[SWITCH_SELECT7]]
+; ALL-NEXT: [[SWITCH_SELECTCMP9:%.*]] = icmp eq i32 [[B]], 0
+; ALL-NEXT: [[SWITCH_SELECT10:%.*]] = select i1 [[SWITCH_SELECTCMP9]], float 2.000000e+00, float 4.000000e+00
+; ALL-NEXT: switch i32 [[B]], label [[RETURN]] [
+; ALL-NEXT: i32 3, label [[SW_BB4:%.*]]
; ALL-NEXT: i32 1, label [[SW_BB2:%.*]]
; ALL-NEXT: i32 2, label [[SW_BB3:%.*]]
-; ALL-NEXT: i32 3, label [[SW_BB4:%.*]]
; ALL-NEXT: ]
-; ALL: sw.bb1:
-; ALL-NEXT: br label [[RETURN]]
; ALL: sw.bb2:
; ALL-NEXT: br label [[RETURN]]
; ALL: sw.bb3:
@@ -212,9 +234,9 @@ define float @partial_constant_multiple_PHInode(i32 %a, i32 %b, float %c, float
; ALL-NEXT: [[TMP2:%.*]] = fneg reassoc nnan nsz arcp contract afn float [[DOTI0]]
; ALL-NEXT: br label [[RETURN]]
; ALL: return:
-; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ [[TMP2]], [[SW_BB4]] ], [ -1.000000e+00, [[SW_BB3]] ], [ [[DOTI0]], [[SW_BB2]] ], [ 1.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
-; ALL-NEXT: [[SAMPLEPOS_1_I1:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ [[DOTI1]], [[SW_BB4]] ], [ [[DOTI1]], [[SW_BB3]] ], [ [[DOTI1]], [[SW_BB2]] ], [ 2.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
-; ALL-NEXT: [[SAMPLEPOS_1_I2:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ -1.000000e+00, [[SW_BB4]] ], [ [[TMP1]], [[SW_BB3]] ], [ 1.000000e+00, [[SW_BB2]] ], [ 3.000000e+00, [[SW_BB1]] ], [ 4.000000e+00, [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I0:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY:%.*]] ], [ [[TMP2]], [[SW_BB4]] ], [ [[SWITCH_SELECT8]], [[SW_BB3]] ], [ [[DOTI0]], [[SW_BB2]] ], [ [[SWITCH_SELECT8]], [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I1:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ [[DOTI1]], [[SW_BB4]] ], [ [[DOTI1]], [[SW_BB3]] ], [ [[DOTI1]], [[SW_BB2]] ], [ [[SWITCH_SELECT10]], [[SW]] ]
+; ALL-NEXT: [[SAMPLEPOS_1_I2:%.*]] = phi float [ 0.000000e+00, [[DOTENTRY]] ], [ [[SWITCH_SELECT4]], [[SW_BB4]] ], [ [[TMP1]], [[SW_BB3]] ], [ [[SWITCH_SELECT4]], [[SW_BB2]] ], [ [[SWITCH_SELECT4]], [[SW]] ]
; ALL-NEXT: [[RETVAL1:%.*]] = fadd float [[SAMPLEPOS_1_I0]], [[SAMPLEPOS_1_I1]]
; ALL-NEXT: [[RETVAL:%.*]] = fadd float [[RETVAL1]], [[SAMPLEPOS_1_I2]]
; ALL-NEXT: ret float [[RETVAL]]
More information about the llvm-commits
mailing list