1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -bonus-inst-threshold=1 | FileCheck --check-prefixes=ALL,THR1 %s 3; RUN: opt < %s -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -bonus-inst-threshold=2 | FileCheck --check-prefixes=ALL,THR2 %s 4 5declare void @sideeffect0() 6declare void @sideeffect1() 7declare void @sideeffect2() 8declare void @use8(i8) 9declare i1 @gen1() 10 11; Here we'd want to duplicate %v3_adj into two predecessors, 12; but -bonus-inst-threshold=1 says that we can only clone it into one. 13; With -bonus-inst-threshold=2 we can clone it into both though. 14define void @two_preds_with_extra_op(i8 %v0, i8 %v1, i8 %v2, i8 %v3) { 15; THR1-LABEL: @two_preds_with_extra_op( 16; THR1-NEXT: entry: 17; THR1-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0 18; THR1-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]] 19; THR1: pred0: 20; THR1-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0 21; THR1-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]] 22; THR1: pred1: 23; THR1-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0 24; THR1-NEXT: br i1 [[C2]], label [[DISPATCH]], label [[FINAL_RIGHT:%.*]] 25; THR1: dispatch: 26; THR1-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]] 27; THR1-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0 28; THR1-NEXT: br i1 [[C3]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]] 29; THR1: common.ret: 30; THR1-NEXT: ret void 31; THR1: final_left: 32; THR1-NEXT: call void @sideeffect0() 33; THR1-NEXT: br label [[COMMON_RET:%.*]] 34; THR1: final_right: 35; THR1-NEXT: call void @sideeffect1() 36; THR1-NEXT: br label [[COMMON_RET]] 37; 38; THR2-LABEL: @two_preds_with_extra_op( 39; THR2-NEXT: entry: 40; THR2-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0 41; THR2-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]] 42; THR2: pred0: 43; THR2-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0 44; THR2-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2:%.*]] 45; THR2-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_OLD]], 0 46; THR2-NEXT: [[OR_COND1:%.*]] = select i1 [[C1]], i1 true, i1 [[C3_OLD]] 47; THR2-NEXT: br i1 [[OR_COND1]], label [[FINAL_LEFT:%.*]], label [[FINAL_RIGHT:%.*]] 48; THR2: pred1: 49; THR2-NEXT: [[C2:%.*]] = icmp eq i8 [[V2]], 0 50; THR2-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]] 51; THR2-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0 52; THR2-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false 53; THR2-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]] 54; THR2: common.ret: 55; THR2-NEXT: ret void 56; THR2: final_left: 57; THR2-NEXT: call void @sideeffect0() 58; THR2-NEXT: br label [[COMMON_RET:%.*]] 59; THR2: final_right: 60; THR2-NEXT: call void @sideeffect1() 61; THR2-NEXT: br label [[COMMON_RET]] 62; 63entry: 64 %c0 = icmp eq i8 %v0, 0 65 br i1 %c0, label %pred0, label %pred1 66pred0: 67 %c1 = icmp eq i8 %v1, 0 68 br i1 %c1, label %final_left, label %dispatch 69pred1: 70 %c2 = icmp eq i8 %v2, 0 71 br i1 %c2, label %dispatch, label %final_right 72dispatch: 73 %v3_adj = add i8 %v1, %v2 74 %c3 = icmp eq i8 %v3_adj, 0 75 br i1 %c3, label %final_left, label %final_right 76final_left: 77 call void @sideeffect0() 78 ret void 79final_right: 80 call void @sideeffect1() 81 ret void 82} 83 84; Here we'd want to duplicate %v3_adj into two predecessors, 85; but -bonus-inst-threshold=1 says that we can only clone it into one. 86; But, we aren't going to clone it into one of the predecessors, 87; because that isn't profitable. So we should not use it in cost calculation. 88define void @two_preds_with_extra_op_and_branchweights(i8 %v0, i8 %v1, i8 %v2, i8 %v3) { 89; ALL-LABEL: @two_preds_with_extra_op_and_branchweights( 90; ALL-NEXT: entry: 91; ALL-NEXT: [[C0:%.*]] = icmp eq i8 [[V0:%.*]], 0 92; ALL-NEXT: br i1 [[C0]], label [[PRED0:%.*]], label [[PRED1:%.*]] 93; ALL: pred0: 94; ALL-NEXT: [[C1:%.*]] = icmp eq i8 [[V1:%.*]], 0 95; ALL-NEXT: br i1 [[C1]], label [[FINAL_LEFT:%.*]], label [[DISPATCH:%.*]], !prof [[PROF0:![0-9]+]] 96; ALL: pred1: 97; ALL-NEXT: [[C2:%.*]] = icmp eq i8 [[V2:%.*]], 0 98; ALL-NEXT: [[V3_ADJ:%.*]] = add i8 [[V1]], [[V2]] 99; ALL-NEXT: [[C3:%.*]] = icmp eq i8 [[V3_ADJ]], 0 100; ALL-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 [[C3]], i1 false 101; ALL-NEXT: br i1 [[OR_COND]], label [[FINAL_LEFT]], label [[FINAL_RIGHT:%.*]] 102; ALL: dispatch: 103; ALL-NEXT: [[V3_ADJ_OLD:%.*]] = add i8 [[V1]], [[V2]] 104; ALL-NEXT: [[C3_OLD:%.*]] = icmp eq i8 [[V3_ADJ_OLD]], 0 105; ALL-NEXT: br i1 [[C3_OLD]], label [[FINAL_LEFT]], label [[FINAL_RIGHT]] 106; ALL: common.ret: 107; ALL-NEXT: ret void 108; ALL: final_left: 109; ALL-NEXT: call void @sideeffect0() 110; ALL-NEXT: br label [[COMMON_RET:%.*]] 111; ALL: final_right: 112; ALL-NEXT: call void @sideeffect1() 113; ALL-NEXT: br label [[COMMON_RET]] 114; 115entry: 116 %c0 = icmp eq i8 %v0, 0 117 br i1 %c0, label %pred0, label %pred1 118pred0: 119 %c1 = icmp eq i8 %v1, 0 120 br i1 %c1, label %final_left, label %dispatch, !prof !0 ; likely branches to %final_left 121pred1: 122 %c2 = icmp eq i8 %v2, 0 123 br i1 %c2, label %dispatch, label %final_right 124dispatch: 125 %v3_adj = add i8 %v1, %v2 126 %c3 = icmp eq i8 %v3_adj, 0 127 br i1 %c3, label %final_left, label %final_right 128final_left: 129 call void @sideeffect0() 130 ret void 131final_right: 132 call void @sideeffect1() 133 ret void 134} 135 136!0 = !{!"branch_weights", i32 99, i32 1} 137 138; CHECK: !0 = !{!"branch_weights", i32 99, i32 1} 139