SwitchInst case values must be ConstantInt, which have no use list. Therefore it is not necessary to store these as Use, instead store them more efficiently as a simple array of pointers after the uses, similar to how PHINode stores basic blocks. After this change, the successors of all terminators are stored consecutively in the operand list. This is preparatory work for improving the performance of successor access. Add new C API functions so that switch case values remain accessible from bindings for other languages. While this could also be achieved by merely changing the order of operands (i.e., first all successors, then all constants), doing so would increase the asymptotic runtime of addCase from O(1) to O(n) (i.e., adding n cases would be O(n^2)), because it would need to shift all constants by one slot. Having null/invalid operands is also a bad idea and would cause much more breakage. Pull Request: https://github.com/llvm/llvm-project/pull/170984
77 lines
2.3 KiB
LLVM
77 lines
2.3 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
|
|
; RUN: opt < %s -passes=simplifycfg -S | FileCheck %s
|
|
|
|
define i32 @nodedup(i1 %c, i16 %v) {
|
|
; CHECK-LABEL: define i32 @nodedup(
|
|
; CHECK-SAME: i1 [[C:%.*]], i16 [[V:%.*]]) {
|
|
; CHECK-NEXT: br i1 [[C]], label %[[B1:.*]], label %[[B2:.*]]
|
|
; CHECK: [[B1]]:
|
|
; CHECK-NEXT: switch i16 [[V]], label %[[RET2:.*]] [
|
|
; CHECK-NEXT: i16 1962, label %[[COMMON_RET:.*]]
|
|
; CHECK-NEXT: i16 2000, label %[[COMMON_RET]]
|
|
; CHECK-NEXT: i16 1963, label %[[COMMON_RET]]
|
|
; CHECK-NEXT: ]
|
|
; CHECK: [[B2]]:
|
|
; CHECK-NEXT: switch i16 [[V]], label %[[RET2]] [
|
|
; CHECK-NEXT: i16 2766, label %[[COMMON_RET]]
|
|
; CHECK-NEXT: i16 2798, label %[[COMMON_RET]]
|
|
; CHECK-NEXT: i16 2767, label %[[COMMON_RET]]
|
|
; CHECK-NEXT: ]
|
|
; CHECK: [[COMMON_RET]]:
|
|
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 3, %[[RET2]] ], [ 1, %[[B2]] ], [ 1, %[[B2]] ], [ 1, %[[B2]] ], [ 1, %[[B1]] ], [ 1, %[[B1]] ], [ 1, %[[B1]] ]
|
|
; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
|
|
; CHECK: [[RET2]]:
|
|
; CHECK-NEXT: br label %[[COMMON_RET]]
|
|
;
|
|
br i1 %c, label %b1, label %b2
|
|
b1:
|
|
switch i16 %v, label %ret2 [
|
|
i16 1962, label %ret1
|
|
i16 2000, label %ret1
|
|
i16 1963, label %ret1
|
|
]
|
|
b2:
|
|
switch i16 %v, label %ret2 [
|
|
i16 2766, label %ret1
|
|
i16 2798, label %ret1
|
|
i16 2767, label %ret1
|
|
]
|
|
ret1:
|
|
ret i32 1
|
|
ret2:
|
|
ret i32 3
|
|
}
|
|
|
|
define i32 @dedup(i1 %c, i16 %v) {
|
|
; CHECK-LABEL: define i32 @dedup(
|
|
; CHECK-SAME: i1 [[C:%.*]], i16 [[V:%.*]]) {
|
|
; CHECK-NEXT: switch i16 [[V]], label %[[RET2:.*]] [
|
|
; CHECK-NEXT: i16 2766, label %[[COMMON_RET:.*]]
|
|
; CHECK-NEXT: i16 2798, label %[[COMMON_RET]]
|
|
; CHECK-NEXT: i16 2767, label %[[COMMON_RET]]
|
|
; CHECK-NEXT: ]
|
|
; CHECK: [[COMMON_RET]]:
|
|
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i32 [ 3, %[[RET2]] ], [ 1, [[TMP0:%.*]] ], [ 1, [[TMP0]] ], [ 1, [[TMP0]] ]
|
|
; CHECK-NEXT: ret i32 [[COMMON_RET_OP]]
|
|
; CHECK: [[RET2]]:
|
|
; CHECK-NEXT: br label %[[COMMON_RET]]
|
|
;
|
|
br i1 %c, label %b1, label %b2
|
|
b1:
|
|
switch i16 %v, label %ret2 [
|
|
i16 2766, label %ret1
|
|
i16 2798, label %ret1
|
|
i16 2767, label %ret1
|
|
]
|
|
b2:
|
|
switch i16 %v, label %ret2 [
|
|
i16 2766, label %ret1
|
|
i16 2798, label %ret1
|
|
i16 2767, label %ret1
|
|
]
|
|
ret1:
|
|
ret i32 1
|
|
ret2:
|
|
ret i32 3
|
|
}
|