blob: 6ea6115147a8f7c8256b3a9dcee4929731371cb9 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
define i32 @default_branch_proves_operand_value(i8 %x) {
; CHECK-LABEL: @default_branch_proves_operand_value(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
; CHECK-NEXT: i8 1, label [[DEFAULT:%.*]]
; CHECK-NEXT: ]
; CHECK: entry.unreachabledefault:
; CHECK-NEXT: unreachable
; CHECK: default:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: br label [[RETURN]]
; CHECK: case_zero:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i32 [[RETVAL]]
;
entry:
switch i8 %x, label %default [
i8 -1, label %case_neg_one
i8 0, label %case_zero
]
default:
%cmp = icmp eq i8 %x, 1
call void @llvm.assume(i1 %cmp)
br label %return
case_neg_one:
br label %return
case_zero:
br label %return
return:
%retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
ret i32 %retval
}
define i32 @default_branch_with_weight_proves_operand_value(i8 %x) {
; CHECK-LABEL: @default_branch_with_weight_proves_operand_value(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
; CHECK-NEXT: i8 1, label [[DEFAULT:%.*]]
; CHECK-NEXT: ], !prof [[PROF0:![0-9]+]]
; CHECK: entry.unreachabledefault:
; CHECK-NEXT: unreachable
; CHECK: default:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: br label [[RETURN]]
; CHECK: case_zero:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i32 [[RETVAL]]
;
entry:
switch i8 %x, label %default [
i8 -1, label %case_neg_one
i8 0, label %case_zero
], !prof !0
default:
%cmp = icmp eq i8 %x, 1
call void @llvm.assume(i1 %cmp)
br label %return
case_neg_one:
br label %return
case_zero:
br label %return
return:
%retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
ret i32 %retval
}
define i32 @default_branch_proves_operand_value_different_blocks(i8 %x) {
; CHECK-LABEL: @default_branch_proves_operand_value_different_blocks(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 1
; CHECK-NEXT: switch i8 [[X]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
; CHECK-NEXT: i8 1, label [[DEFAULT:%.*]]
; CHECK-NEXT: ]
; CHECK: entry.unreachabledefault:
; CHECK-NEXT: unreachable
; CHECK: default:
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: br label [[RETURN]]
; CHECK: case_zero:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i32 [[RETVAL]]
;
entry:
%cmp = icmp eq i8 %x, 1
switch i8 %x, label %default [
i8 -1, label %case_neg_one
i8 0, label %case_zero
]
default:
call void @llvm.assume(i1 %cmp)
br label %return
case_neg_one:
br label %return
case_zero:
br label %return
return:
%retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
ret i32 %retval
}
declare void @foo(i8 %bar) nounwind
define i32 @default_branch_proves_operand_value_assume_operand_not_ephemeral(i8 %x) {
; CHECK-LABEL: @default_branch_proves_operand_value_assume_operand_not_ephemeral(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
; CHECK-NEXT: i8 1, label [[DEFAULT:%.*]]
; CHECK-NEXT: ]
; CHECK: entry.unreachabledefault:
; CHECK-NEXT: unreachable
; CHECK: default:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: call void @foo(i1 [[CMP]])
; CHECK-NEXT: br label [[RETURN]]
; CHECK: case_zero:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i32 [[RETVAL]]
;
entry:
switch i8 %x, label %default [
i8 -1, label %case_neg_one
i8 0, label %case_zero
]
default:
%cmp = icmp eq i8 %x, 1
call void @llvm.assume(i1 %cmp)
call void @foo(i1 %cmp)
br label %return
case_neg_one:
br label %return
case_zero:
br label %return
return:
%retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
ret i32 %retval
}
define i32 @default_branch_proves_operand_value_but_has_existing_case(i8 %x) {
; CHECK-LABEL: @default_branch_proves_operand_value_but_has_existing_case(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
; CHECK-NEXT: i8 1, label [[CASE_ONE:%.*]]
; CHECK-NEXT: ]
; CHECK: entry.unreachabledefault:
; CHECK-NEXT: unreachable
; CHECK: case_zero:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: case_one:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[CASE_ONE]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i32 [[RETVAL]]
;
entry:
switch i8 %x, label %default [
i8 -1, label %case_neg_one
i8 0, label %case_zero
i8 1, label %case_one
]
default:
%cmp = icmp eq i8 %x, 1
call void @llvm.assume(i1 %cmp)
br label %return
case_neg_one:
br label %return
case_zero:
br label %return
case_one:
br label %return
return:
%retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ], [1, %case_one ]
ret i32 %retval
}
define i32 @default_branch_assume_doesnt_prove_all_bits(i8 %x) {
; CHECK-LABEL: @default_branch_assume_doesnt_prove_all_bits(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i8 [[X:%.*]], label [[DEFAULT:%.*]] [
; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
; CHECK-NEXT: ]
; CHECK: default:
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[X]], 10
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: br label [[RETURN]]
; CHECK: case_zero:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i32 [[RETVAL]]
;
entry:
switch i8 %x, label %default [
i8 -1, label %case_neg_one
i8 0, label %case_zero
]
default:
%cmp = icmp ule i8 %x, 10
call void @llvm.assume(i1 %cmp)
br label %return
case_neg_one:
br label %return
case_zero:
br label %return
return:
%retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
ret i32 %retval
}
declare void @foo_may_unwind()
define i32 @default_branch_may_throw_before_assume(i8 %x) {
; CHECK-LABEL: @default_branch_may_throw_before_assume(
; CHECK-NEXT: entry:
; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
; CHECK-NEXT: ]
; CHECK: default:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
; CHECK-NEXT: call void @foo_may_unwind()
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: br label [[RETURN]]
; CHECK: case_zero:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[ENTRY_UNREACHABLEDEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY:%.*]] ]
; CHECK-NEXT: ret i32 [[RETVAL]]
;
entry:
switch i8 %x, label %default [
i8 -1, label %case_neg_one
i8 0, label %case_zero
]
default:
%cmp = icmp eq i8 %x, 1
call void @foo_may_unwind()
call void @llvm.assume(i1 %cmp)
br label %return
case_neg_one:
br label %return
case_zero:
br label %return
return:
%retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
ret i32 %retval
}
; Make sure to properly update PHINode block entries if the default branch
; happens to have them.
declare i1 @some_use(i8)
define i32 @default_branch_has_phi_and_will_be_moved(i8 %x, i1 %y) {
; CHECK-LABEL: @default_branch_has_phi_and_will_be_moved(
; CHECK-NEXT: pre-entry:
; CHECK-NEXT: br i1 [[Y:%.*]], label [[ENTRY:%.*]], label [[DEFAULT:%.*]]
; CHECK: entry:
; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
; CHECK-NEXT: i8 1, label [[DEFAULT]]
; CHECK-NEXT: ]
; CHECK: entry.unreachabledefault:
; CHECK-NEXT: unreachable
; CHECK: default:
; CHECK-NEXT: [[Z:%.*]] = phi i8 [ 2, [[PRE_ENTRY:%.*]] ], [ 3, [[ENTRY]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: call void @some_use(i8 [[Z]])
; CHECK-NEXT: br label [[RETURN]]
; CHECK: case_zero:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY]] ]
; CHECK-NEXT: ret i32 [[RETVAL]]
;
pre-entry:
br i1 %y, label %entry, label %default
entry:
switch i8 %x, label %default [
i8 -1, label %case_neg_one
i8 0, label %case_zero
]
default:
%z = phi i8 [ 2, %pre-entry], [ 3, %entry]
%cmp = icmp eq i8 %x, 1
call void @llvm.assume(i1 %cmp)
call void @some_use(i8 %z)
br label %return
case_neg_one:
br label %return
case_zero:
br label %return
return:
%retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
ret i32 %retval
}
define i32 @default_branch_has_phi_and_will_be_removed(i8 %x, i1 %y) {
; CHECK-LABEL: @default_branch_has_phi_and_will_be_removed(
; CHECK-NEXT: pre-entry:
; CHECK-NEXT: br i1 [[Y:%.*]], label [[ENTRY:%.*]], label [[DEFAULT:%.*]]
; CHECK: entry:
; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
; CHECK-NEXT: i8 1, label [[CASE_ONE:%.*]]
; CHECK-NEXT: ]
; CHECK: entry.unreachabledefault:
; CHECK-NEXT: unreachable
; CHECK: default:
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: call void @some_use(i8 2)
; CHECK-NEXT: br label [[RETURN]]
; CHECK: case_zero:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: case_one:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 1, [[CASE_ONE]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY]] ]
; CHECK-NEXT: ret i32 [[RETVAL]]
;
pre-entry:
br i1 %y, label %entry, label %default
entry:
switch i8 %x, label %default [
i8 -1, label %case_neg_one
i8 0, label %case_zero
i8 1, label %case_one
]
default:
%z = phi i8 [ 2, %pre-entry], [ 3, %entry]
%cmp = icmp eq i8 %x, 1
call void @llvm.assume(i1 %cmp)
call void @some_use(i8 %z)
br label %return
case_neg_one:
br label %return
case_zero:
br label %return
case_one:
br label %return
return:
%retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ], [ 1, %case_one ]
ret i32 %retval
}
define i32 @default_branch_has_phi_and_will_be_removed_duplicate_phi_entries(i8 %x, i1 %y) {
; CHECK-LABEL: @default_branch_has_phi_and_will_be_removed_duplicate_phi_entries(
; CHECK-NEXT: pre-entry:
; CHECK-NEXT: br i1 [[Y:%.*]], label [[ENTRY:%.*]], label [[DEFAULT:%.*]]
; CHECK: entry:
; CHECK-NEXT: switch i8 [[X:%.*]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
; CHECK-NEXT: i8 -1, label [[RETURN:%.*]]
; CHECK-NEXT: i8 0, label [[CASE_ZERO:%.*]]
; CHECK-NEXT: i8 1, label [[DEFAULT]]
; CHECK-NEXT: ]
; CHECK: entry.unreachabledefault:
; CHECK-NEXT: unreachable
; CHECK: default:
; CHECK-NEXT: [[Z:%.*]] = phi i8 [ 2, [[PRE_ENTRY:%.*]] ], [ 3, [[ENTRY]] ]
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 1
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: call void @some_use(i8 [[Z]])
; CHECK-NEXT: br label [[RETURN]]
; CHECK: case_zero:
; CHECK-NEXT: br label [[RETURN]]
; CHECK: return:
; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 1, [[DEFAULT]] ], [ 0, [[CASE_ZERO]] ], [ -1, [[ENTRY]] ]
; CHECK-NEXT: ret i32 [[RETVAL]]
;
pre-entry:
br i1 %y, label %entry, label %default
entry:
switch i8 %x, label %default [
i8 -1, label %case_neg_one
i8 0, label %case_zero
i8 1, label %default
]
default:
%z = phi i8 [ 2, %pre-entry], [ 3, %entry], [ 3, %entry ]
%cmp = icmp eq i8 %x, 1
call void @llvm.assume(i1 %cmp)
call void @some_use(i8 %z)
br label %return
case_neg_one:
br label %return
case_zero:
br label %return
return:
%retval = phi i32 [ 1, %default ], [ -1, %case_neg_one ], [ 0, %case_zero ]
ret i32 %retval
}
; CHECK: [[PROF0]] = !{!"branch_weights", i32 0, i32 4, i32 2, i32 8}
!0 = !{!"branch_weights", i32 8, i32 4, i32 2}