| ; 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 | FileCheck %s | |
| define void @ucmp_gt1(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt1( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @ucmp_gt2(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt2( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 0, label %bb2 | |
| i8 -1, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @ucmp_lt1(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_lt1( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB2:.*]], label %[[BB1:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb2 [ | |
| i8 1, label %bb1 | |
| i8 0, label %bb1 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @ucmp_lt2(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_lt2( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB2:.*]], label %[[BB1:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb2 [ | |
| i8 0, label %bb1 | |
| i8 1, label %bb1 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @ucmp_eq1(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_eq1( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 -1, label %bb2 | |
| i8 1, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @ucmp_eq2(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_eq2( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 1, label %bb2 | |
| i8 -1, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @scmp_gt1(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @scmp_gt1( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.scmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @scmp_gt2(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @scmp_gt2( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.scmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 0, label %bb2 | |
| i8 -1, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @ucmp_gt_multiuse(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_multiuse( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]]) | |
| ; CHECK-NEXT: call void @use(i8 [[RES]]) | |
| ; CHECK-NEXT: switch i8 [[RES]], label %[[BB1:.*]] [ | |
| ; CHECK-NEXT: i8 -1, label %[[BB2:.*]] | |
| ; CHECK-NEXT: i8 0, label %[[BB2]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| call void @use(i8 %res) | |
| switch i8 %res, label %bb1 [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define i32 @ucmp_gt_phi(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define i32 @ucmp_gt_phi( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*]]: | |
| ; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP0]], label %[[BB1:.*]], label %[[BB2:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, %[[BB1]] ], [ 1, %[[ENTRY]] ] | |
| ; CHECK-NEXT: ret i32 [[PHI]] | |
| ; | |
| entry: | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| %phi = phi i32 [ 0, %bb1 ], [ 1, %entry ], [ 1, %entry ] | |
| ret i32 %phi | |
| } | |
| define void @ucmp_gt_extra_case(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_extra_case( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]]) | |
| ; CHECK-NEXT: switch i8 [[RES]], label %[[BB1:.*]] [ | |
| ; CHECK-NEXT: i8 -1, label %[[BB2:.*]] | |
| ; CHECK-NEXT: i8 0, label %[[BB2]] | |
| ; CHECK-NEXT: i8 1, label %[[BB2]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb2 | |
| i8 1, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @ucmp_gt_wrong_case(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_wrong_case( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]]) | |
| ; CHECK-NEXT: switch i8 [[RES]], label %[[BB1:.*]] [ | |
| ; CHECK-NEXT: i8 -2, label %[[BB2:.*]] | |
| ; CHECK-NEXT: i8 0, label %[[BB2]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 -2, label %bb2 | |
| i8 0, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @ucmp_gt_not_same_succ(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_not_same_succ( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]]) | |
| ; CHECK-NEXT: switch i8 [[RES]], label %[[BB1:.*]] [ | |
| ; CHECK-NEXT: i8 -1, label %[[BB2:.*]] | |
| ; CHECK-NEXT: i8 0, label %[[BB3:.*]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB3]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb3 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb3: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @ucmp_gt_unpredictable(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_unpredictable( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]], !unpredictable [[META0:![0-9]+]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb2 | |
| ], !unpredictable !{} | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @ucmp_gt_weights(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_weights( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]], !prof [[PROF1:![0-9]+]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %bb1 [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb2 | |
| ], !prof !{!"branch_weights", i32 5, i32 10, i32 20} | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| } | |
| define void @ucmp_gt_unreachable(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_unreachable( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %unreachable [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb2 | |
| i8 1, label %bb1 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| unreachable: | |
| unreachable | |
| } | |
| define void @ucmp_lt_unreachable(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_lt_unreachable( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %unreachable [ | |
| i8 -1, label %bb1 | |
| i8 0, label %bb2 | |
| i8 1, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| unreachable: | |
| unreachable | |
| } | |
| define void @ucmp_eq_unreachable(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_eq_unreachable( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %unreachable [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb1 | |
| i8 1, label %bb2 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| unreachable: | |
| unreachable | |
| } | |
| define void @ucmp_gt_unreachable_multi_edge(i8 %x, i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_unreachable_multi_edge( | |
| ; CHECK-SAME: i8 [[X:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[ENTRY:.*:]] | |
| ; CHECK-NEXT: switch i8 [[X]], label %[[UNREACHABLE:.*]] [ | |
| ; CHECK-NEXT: i8 0, label %[[SW:.*]] | |
| ; CHECK-NEXT: i8 1, label %[[BB1:.*]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: [[SW]]: | |
| ; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP0]], label %[[BB1]], label %[[BB2:.*]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: [[UNREACHABLE]]: | |
| ; CHECK-NEXT: unreachable | |
| ; | |
| entry: | |
| switch i8 %x, label %unreachable [ | |
| i8 0, label %sw | |
| i8 1, label %bb1 | |
| ] | |
| sw: | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %unreachable [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb2 | |
| i8 1, label %bb1 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| unreachable: | |
| %phi = phi i32 [ 0, %entry ], [ 1, %sw ] | |
| unreachable | |
| } | |
| define void @ucmp_gt_unreachable_wrong_case(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_unreachable_wrong_case( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]]) | |
| ; CHECK-NEXT: switch i8 [[RES]], label %[[UNREACHABLE:.*]] [ | |
| ; CHECK-NEXT: i8 -2, label %[[BB2:.*]] | |
| ; CHECK-NEXT: i8 0, label %[[BB2]] | |
| ; CHECK-NEXT: i8 1, label %[[BB1:.*]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: [[UNREACHABLE]]: | |
| ; CHECK-NEXT: unreachable | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %unreachable [ | |
| i8 -2, label %bb2 | |
| i8 0, label %bb2 | |
| i8 1, label %bb1 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| unreachable: | |
| unreachable | |
| } | |
| define void @ucmp_gt_unreachable_no_two_equal_cases(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_unreachable_no_two_equal_cases( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]]) | |
| ; CHECK-NEXT: switch i8 [[RES]], label %[[UNREACHABLE:.*]] [ | |
| ; CHECK-NEXT: i8 -1, label %[[BB3:.*]] | |
| ; CHECK-NEXT: i8 0, label %[[BB2:.*]] | |
| ; CHECK-NEXT: i8 1, label %[[BB1:.*]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB3]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: [[UNREACHABLE]]: | |
| ; CHECK-NEXT: unreachable | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %unreachable [ | |
| i8 -1, label %bb3 | |
| i8 0, label %bb2 | |
| i8 1, label %bb1 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb3: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| unreachable: | |
| unreachable | |
| } | |
| define void @ucmp_gt_unreachable_three_equal_cases(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_unreachable_three_equal_cases( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[BB1:.*:]] | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %unreachable [ | |
| i8 -1, label %bb1 | |
| i8 0, label %bb1 | |
| i8 1, label %bb1 | |
| ] | |
| bb1: | |
| call void @foo() | |
| ret void | |
| unreachable: | |
| unreachable | |
| } | |
| define void @ucmp_gt_unreachable_default_not_unreachable(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_unreachable_default_not_unreachable( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[A]], i32 [[B]]) | |
| ; CHECK-NEXT: switch i8 [[RES]], label %[[NOT_UNREACHABLE:.*]] [ | |
| ; CHECK-NEXT: i8 -1, label %[[BB2:.*]] | |
| ; CHECK-NEXT: i8 0, label %[[BB2]] | |
| ; CHECK-NEXT: i8 1, label %[[BB1:.*]] | |
| ; CHECK-NEXT: ] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; CHECK: [[NOT_UNREACHABLE]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %not.unreachable [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb2 | |
| i8 1, label %bb1 | |
| ] | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| not.unreachable: | |
| call void @foo() | |
| br label %bb2 | |
| } | |
| define void @ucmp_gt_unreachable_weights(i32 %a, i32 %b) { | |
| ; CHECK-LABEL: define void @ucmp_gt_unreachable_weights( | |
| ; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) { | |
| ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A]], [[B]] | |
| ; CHECK-NEXT: br i1 [[TMP1]], label %[[BB1:.*]], label %[[BB2:.*]], !prof [[PROF1]] | |
| ; CHECK: [[BB1]]: | |
| ; CHECK-NEXT: call void @foo() | |
| ; CHECK-NEXT: br label %[[BB2]] | |
| ; CHECK: [[BB2]]: | |
| ; CHECK-NEXT: ret void | |
| ; | |
| %res = call i8 @llvm.ucmp.i8.i32(i32 %a, i32 %b) | |
| switch i8 %res, label %unreachable [ | |
| i8 -1, label %bb2 | |
| i8 0, label %bb2 | |
| i8 1, label %bb1 | |
| ], !prof !{!"branch_weights", i32 0, i32 10, i32 20, i32 5} | |
| bb1: | |
| call void @foo() | |
| br label %bb2 | |
| bb2: | |
| ret void | |
| unreachable: | |
| unreachable | |
| } | |
| declare void @use(i8) | |
| declare void @foo() | |
| ;. | |
| ; CHECK: [[META0]] = !{} | |
| ; CHECK: [[PROF1]] = !{!"branch_weights", i32 5, i32 30} | |
| ;. |