
Avoid repeatedly querying `getUniquePredecessor` for already-visited switch successors so as not to incur quadratic runtime. Fixes: https://github.com/llvm/llvm-project/issues/147239.
243 lines
6.8 KiB
LLVM
243 lines
6.8 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S \
|
|
; RUN: | FileCheck %s -check-prefix=SIMPLIFY-CFG
|
|
|
|
define i32 @switch_all_duplicate_arms(i32 %0, i32 %1, i32 %2, i32 %3) {
|
|
; SIMPLIFY-CFG-LABEL: define i32 @switch_all_duplicate_arms(
|
|
; SIMPLIFY-CFG-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]]) {
|
|
; SIMPLIFY-CFG-NEXT: switch i32 [[TMP1]], label %[[BB6:.*]] [
|
|
; SIMPLIFY-CFG-NEXT: i32 0, label %[[BB5:.*]]
|
|
; SIMPLIFY-CFG-NEXT: i32 1, label %[[BB5]]
|
|
; SIMPLIFY-CFG-NEXT: ]
|
|
; SIMPLIFY-CFG: [[BB5]]:
|
|
; SIMPLIFY-CFG-NEXT: br label %[[BB6]]
|
|
; SIMPLIFY-CFG: [[BB6]]:
|
|
; SIMPLIFY-CFG-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP3]], [[TMP4:%.*]] ], [ [[TMP2]], %[[BB5]] ]
|
|
; SIMPLIFY-CFG-NEXT: ret i32 [[TMP8]]
|
|
;
|
|
switch i32 %1, label %7 [
|
|
i32 0, label %5
|
|
i32 1, label %6
|
|
]
|
|
|
|
5:
|
|
br label %7
|
|
|
|
6:
|
|
br label %7
|
|
|
|
7:
|
|
%8 = phi i32 [ %3, %4 ], [ %2, %6 ], [ %2, %5 ]
|
|
ret i32 %8
|
|
}
|
|
|
|
define i32 @switch_some_duplicate_arms(i32 %0, i32 %1, i32 %2, i32 %3, i32 %4) {
|
|
; SIMPLIFY-CFG-LABEL: define i32 @switch_some_duplicate_arms(
|
|
; SIMPLIFY-CFG-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]], i32 [[TMP4:%.*]]) {
|
|
; SIMPLIFY-CFG-NEXT: switch i32 [[TMP1]], label %[[BB8:.*]] [
|
|
; SIMPLIFY-CFG-NEXT: i32 0, label %[[BB6:.*]]
|
|
; SIMPLIFY-CFG-NEXT: i32 1, label %[[BB6]]
|
|
; SIMPLIFY-CFG-NEXT: i32 2, label %[[BB7:.*]]
|
|
; SIMPLIFY-CFG-NEXT: ]
|
|
; SIMPLIFY-CFG: [[BB6]]:
|
|
; SIMPLIFY-CFG-NEXT: br label %[[BB8]]
|
|
; SIMPLIFY-CFG: [[BB7]]:
|
|
; SIMPLIFY-CFG-NEXT: br label %[[BB8]]
|
|
; SIMPLIFY-CFG: [[BB8]]:
|
|
; SIMPLIFY-CFG-NEXT: [[TMP10:%.*]] = phi i32 [ [[TMP3]], [[TMP5:%.*]] ], [ [[TMP4]], %[[BB7]] ], [ [[TMP2]], %[[BB6]] ]
|
|
; SIMPLIFY-CFG-NEXT: ret i32 [[TMP10]]
|
|
;
|
|
switch i32 %1, label %9 [
|
|
i32 0, label %6
|
|
i32 1, label %7
|
|
i32 2, label %8
|
|
]
|
|
|
|
6:
|
|
br label %9
|
|
|
|
7:
|
|
br label %9
|
|
|
|
8:
|
|
br label %9
|
|
|
|
9:
|
|
%10 = phi i32 [ %3, %5 ], [ %4, %8 ], [ %2, %7 ], [ %2, %6 ]
|
|
ret i32 %10
|
|
}
|
|
|
|
define i32 @switch_duplicate_arms_multipred(i1 %0, i32 %1, i32 %2, i32 %3, i32 %4) {
|
|
; SIMPLIFY-CFG-LABEL: define i32 @switch_duplicate_arms_multipred(
|
|
; SIMPLIFY-CFG-SAME: i1 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]], i32 [[TMP4:%.*]]) {
|
|
; SIMPLIFY-CFG-NEXT: br i1 [[TMP0]], label %[[BB6:.*]], label %[[BB7:.*]]
|
|
; SIMPLIFY-CFG: [[BB6]]:
|
|
; SIMPLIFY-CFG-NEXT: switch i32 [[TMP2]], label %[[BB9:.*]] [
|
|
; SIMPLIFY-CFG-NEXT: i32 0, label %[[BB7]]
|
|
; SIMPLIFY-CFG-NEXT: i32 1, label %[[BB8:.*]]
|
|
; SIMPLIFY-CFG-NEXT: ]
|
|
; SIMPLIFY-CFG: [[BB7]]:
|
|
; SIMPLIFY-CFG-NEXT: br label %[[BB9]]
|
|
; SIMPLIFY-CFG: [[BB8]]:
|
|
; SIMPLIFY-CFG-NEXT: br label %[[BB9]]
|
|
; SIMPLIFY-CFG: [[BB9]]:
|
|
; SIMPLIFY-CFG-NEXT: [[TMP10:%.*]] = phi i32 [ [[TMP4]], %[[BB6]] ], [ [[TMP3]], %[[BB8]] ], [ [[TMP3]], %[[BB7]] ]
|
|
; SIMPLIFY-CFG-NEXT: ret i32 [[TMP10]]
|
|
;
|
|
br i1 %0, label %6, label %7
|
|
6:
|
|
switch i32 %2, label %9 [
|
|
i32 0, label %7
|
|
i32 1, label %8
|
|
]
|
|
|
|
7:
|
|
br label %9
|
|
|
|
8:
|
|
br label %9
|
|
|
|
9:
|
|
%10 = phi i32 [ %4, %6 ], [ %3, %8 ], [ %3, %7 ]
|
|
ret i32 %10
|
|
}
|
|
|
|
define i32 @switch_dup_default(i32 %0, i32 %1, i32 %2, i32 %3) {
|
|
; SIMPLIFY-CFG-LABEL: define i32 @switch_dup_default(
|
|
; SIMPLIFY-CFG-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]]) {
|
|
; SIMPLIFY-CFG-NEXT: [[COND:%.*]] = icmp eq i32 [[TMP1]], 0
|
|
; SIMPLIFY-CFG-NEXT: [[TMP8:%.*]] = select i1 [[COND]], i32 [[TMP3]], i32 [[TMP2]]
|
|
; SIMPLIFY-CFG-NEXT: ret i32 [[TMP8]]
|
|
;
|
|
switch i32 %1, label %7 [
|
|
i32 0, label %5
|
|
i32 1, label %6
|
|
]
|
|
|
|
5:
|
|
br label %8
|
|
|
|
6:
|
|
br label %8
|
|
|
|
7:
|
|
br label %8
|
|
|
|
8:
|
|
%9 = phi i32 [ %3, %5 ], [ %2, %6 ], [ %2, %7 ]
|
|
ret i32 %9
|
|
}
|
|
|
|
define i32 @switch_dup_exit(i32 %val) {
|
|
; SIMPLIFY-CFG-LABEL: define i32 @switch_dup_exit(
|
|
; SIMPLIFY-CFG-SAME: i32 [[VAL:%.*]]) {
|
|
; SIMPLIFY-CFG-NEXT: [[ENTRY:.*]]:
|
|
; SIMPLIFY-CFG-NEXT: switch i32 [[VAL]], label %[[DEFAULT:.*]] [
|
|
; SIMPLIFY-CFG-NEXT: i32 1, label %[[EXIT:.*]]
|
|
; SIMPLIFY-CFG-NEXT: i32 11, label %[[EXIT]]
|
|
; SIMPLIFY-CFG-NEXT: i32 22, label %[[BB1:.*]]
|
|
; SIMPLIFY-CFG-NEXT: ]
|
|
; SIMPLIFY-CFG: [[BB1]]:
|
|
; SIMPLIFY-CFG-NEXT: br label %[[EXIT]]
|
|
; SIMPLIFY-CFG: [[DEFAULT]]:
|
|
; SIMPLIFY-CFG-NEXT: br label %[[EXIT]]
|
|
; SIMPLIFY-CFG: [[EXIT]]:
|
|
; SIMPLIFY-CFG-NEXT: [[RET:%.*]] = phi i32 [ 0, %[[DEFAULT]] ], [ 3, %[[BB1]] ], [ 1, %[[ENTRY]] ], [ 1, %[[ENTRY]] ]
|
|
; SIMPLIFY-CFG-NEXT: ret i32 [[RET]]
|
|
;
|
|
entry:
|
|
switch i32 %val, label %default [
|
|
i32 1, label %exit
|
|
i32 11, label %exit
|
|
i32 22, label %bb1
|
|
i32 15, label %bb2
|
|
i32 0, label %bb2
|
|
]
|
|
|
|
bb1:
|
|
br label %exit
|
|
|
|
bb2:
|
|
br label %exit
|
|
|
|
default:
|
|
br label %exit
|
|
|
|
exit:
|
|
%ret = phi i32 [ 0, %default ], [ 0, %bb2 ], [ 3, %bb1 ], [ 1, %entry ], [ 1, %entry ]
|
|
ret i32 %ret
|
|
}
|
|
|
|
define i64 @switch_dup_exit_2(i32 %val) {
|
|
; SIMPLIFY-CFG-LABEL: define i64 @switch_dup_exit_2(
|
|
; SIMPLIFY-CFG-SAME: i32 [[VAL:%.*]]) {
|
|
; SIMPLIFY-CFG-NEXT: [[ENTRY:.*:]]
|
|
; SIMPLIFY-CFG-NEXT: [[SWITCH_SELECTCMP_CASE1:%.*]] = icmp eq i32 [[VAL]], 1
|
|
; SIMPLIFY-CFG-NEXT: [[SWITCH_SELECTCMP_CASE2:%.*]] = icmp eq i32 [[VAL]], 11
|
|
; SIMPLIFY-CFG-NEXT: [[SWITCH_SELECTCMP:%.*]] = or i1 [[SWITCH_SELECTCMP_CASE1]], [[SWITCH_SELECTCMP_CASE2]]
|
|
; SIMPLIFY-CFG-NEXT: [[RET:%.*]] = select i1 [[SWITCH_SELECTCMP]], i64 1, i64 0
|
|
; SIMPLIFY-CFG-NEXT: ret i64 [[RET]]
|
|
;
|
|
entry:
|
|
switch i32 %val, label %default [
|
|
i32 1, label %bb2
|
|
i32 11, label %exit
|
|
i32 13, label %bb1
|
|
i32 0, label %bb1
|
|
]
|
|
|
|
bb1:
|
|
br label %exit
|
|
|
|
bb2:
|
|
br label %exit
|
|
|
|
default:
|
|
br label %exit
|
|
|
|
exit:
|
|
%ret = phi i64 [ 0, %default ], [ 0, %bb1 ], [ 1, %entry ], [ 1, %bb2 ]
|
|
ret i64 %ret
|
|
}
|
|
|
|
define i32 @switch_dup_unbounded_predecessors(i32 %val) {
|
|
; SIMPLIFY-CFG-LABEL: define i32 @switch_dup_unbounded_predecessors(
|
|
; SIMPLIFY-CFG-SAME: i32 [[VAL:%.*]]) {
|
|
; SIMPLIFY-CFG-NEXT: [[ENTRY:.*]]:
|
|
; SIMPLIFY-CFG-NEXT: switch i32 [[VAL]], label %[[EXIT:.*]] [
|
|
; SIMPLIFY-CFG-NEXT: i32 99, label %[[BB1:.*]]
|
|
; SIMPLIFY-CFG-NEXT: i32 115, label %[[BB1]]
|
|
; SIMPLIFY-CFG-NEXT: i32 102, label %[[BB1]]
|
|
; SIMPLIFY-CFG-NEXT: i32 70, label %[[BB1]]
|
|
; SIMPLIFY-CFG-NEXT: i32 101, label %[[BB1]]
|
|
; SIMPLIFY-CFG-NEXT: i32 69, label %[[BB1]]
|
|
; SIMPLIFY-CFG-NEXT: i32 103, label %[[BB1]]
|
|
; SIMPLIFY-CFG-NEXT: ]
|
|
; SIMPLIFY-CFG: [[BB1]]:
|
|
; SIMPLIFY-CFG-NEXT: br label %[[EXIT]]
|
|
; SIMPLIFY-CFG: [[EXIT]]:
|
|
; SIMPLIFY-CFG-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ 1, %[[BB1]] ]
|
|
; SIMPLIFY-CFG-NEXT: ret i32 [[PHI]]
|
|
;
|
|
entry:
|
|
switch i32 %val, label %exit [
|
|
i32 99, label %bb1
|
|
i32 115, label %bb1
|
|
i32 102, label %bb2
|
|
i32 70, label %bb2
|
|
i32 101, label %bb2
|
|
i32 69, label %bb2
|
|
i32 103, label %bb2
|
|
]
|
|
|
|
bb1:
|
|
br label %exit
|
|
|
|
bb2:
|
|
br label %exit
|
|
|
|
exit:
|
|
%phi = phi i32 [ 0, %entry ], [ 1, %bb1 ], [ 1, %bb2 ]
|
|
ret i32 %phi
|
|
}
|