1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -mtriple=thumbv8.1m.main -simplifycfg -S %s -o - | FileCheck %s --check-prefix=V8M 3; RUN: opt -mtriple=thumbv8m.main -simplifycfg -S %s -o - | FileCheck %s --check-prefix=V8M 4; RUN: opt -mtriple=thumbv8m.base -simplifycfg -S %s -o - | FileCheck %s --check-prefix=V8M 5; RUN: opt -mtriple=armv8a -simplifycfg -S %s -o - | FileCheck %s --check-prefix=V8A 6 7; Test that the phis from for.inc.preheader aren't hoisted into sw.bb92 because 8; the cost is too great - we can make a better decision later on. 9; FIXME: The Arm cost model needs to be updated for SizeAndLatency. 10define i32 @multiple_spec_select_costs(i8* %a, i32* %idx, i8 %in) { 11; V8M-LABEL: @multiple_spec_select_costs( 12; V8M-NEXT: entry: 13; V8M-NEXT: [[GEP_A_2:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i32 2 14; V8M-NEXT: [[INCDEC_PTR109_C4:%.*]] = getelementptr inbounds i8, i8* [[A]], i32 3 15; V8M-NEXT: [[ZERO:%.*]] = icmp ne i8 [[IN:%.*]], 0 16; V8M-NEXT: br i1 [[ZERO]], label [[FOR_INC_PREHEADER:%.*]], label [[SW_BB92:%.*]] 17; V8M: sw.bb92: 18; V8M-NEXT: [[C_OFF_I150:%.*]] = add i8 [[IN]], -48 19; V8M-NEXT: [[UGT_9:%.*]] = icmp ugt i8 [[C_OFF_I150]], 9 20; V8M-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[UGT_9]], i1 false, i1 true 21; V8M-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[UGT_9]], i32 1, i32 7 22; V8M-NEXT: br label [[FOR_INC_PREHEADER]] 23; V8M: for.inc.preheader: 24; V8M-NEXT: [[STR_PH_0:%.*]] = phi i8* [ [[GEP_A_2]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR109_C4]], [[SW_BB92]] ] 25; V8M-NEXT: [[CMP:%.*]] = phi i1 [ false, [[ENTRY]] ], [ [[SPEC_SELECT]], [[SW_BB92]] ] 26; V8M-NEXT: [[PHI_RES:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[SPEC_SELECT1]], [[SW_BB92]] ] 27; V8M-NEXT: br label [[FOR_INC:%.*]] 28; V8M: for.inc: 29; V8M-NEXT: [[STR_PH_1:%.*]] = phi i8* [ [[INCDEC_PTR109:%.*]], [[FOR_BODY:%.*]] ], [ [[STR_PH_0]], [[FOR_INC_PREHEADER]] ] 30; V8M-NEXT: [[INCDEC_PTR109]] = getelementptr inbounds i8, i8* [[STR_PH_1]], i32 1 31; V8M-NEXT: [[LOAD_1:%.*]] = load i8, i8* [[INCDEC_PTR109]], align 1 32; V8M-NEXT: [[TOBOOL:%.*]] = icmp ne i8 [[LOAD_1]], 0 33; V8M-NEXT: [[AND:%.*]] = and i1 [[CMP]], [[TOBOOL]] 34; V8M-NEXT: br i1 [[AND]], label [[FOR_BODY]], label [[EXIT:%.*]] 35; V8M: for.body: 36; V8M-NEXT: [[CMP_1:%.*]] = icmp eq i8 [[LOAD_1]], 1 37; V8M-NEXT: br i1 [[CMP_1]], label [[FOR_INC]], label [[SW_BB92]] 38; V8M: exit: 39; V8M-NEXT: ret i32 [[PHI_RES]] 40; 41; V8A-LABEL: @multiple_spec_select_costs( 42; V8A-NEXT: entry: 43; V8A-NEXT: [[GEP_A_2:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i32 2 44; V8A-NEXT: [[INCDEC_PTR109_C4:%.*]] = getelementptr inbounds i8, i8* [[A]], i32 3 45; V8A-NEXT: [[ZERO:%.*]] = icmp ne i8 [[IN:%.*]], 0 46; V8A-NEXT: br i1 [[ZERO]], label [[FOR_INC_PREHEADER:%.*]], label [[SW_BB92:%.*]] 47; V8A: sw.bb92: 48; V8A-NEXT: [[C_OFF_I150:%.*]] = add i8 [[IN]], -48 49; V8A-NEXT: [[UGT_9:%.*]] = icmp ugt i8 [[C_OFF_I150]], 9 50; V8A-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[UGT_9]], i1 false, i1 true 51; V8A-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[UGT_9]], i32 1, i32 7 52; V8A-NEXT: br label [[FOR_INC_PREHEADER]] 53; V8A: for.inc.preheader: 54; V8A-NEXT: [[STR_PH_0:%.*]] = phi i8* [ [[GEP_A_2]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR109_C4]], [[SW_BB92]] ] 55; V8A-NEXT: [[CMP:%.*]] = phi i1 [ false, [[ENTRY]] ], [ [[SPEC_SELECT]], [[SW_BB92]] ] 56; V8A-NEXT: [[PHI_RES:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[SPEC_SELECT1]], [[SW_BB92]] ] 57; V8A-NEXT: br label [[FOR_INC:%.*]] 58; V8A: for.inc: 59; V8A-NEXT: [[STR_PH_1:%.*]] = phi i8* [ [[INCDEC_PTR109:%.*]], [[FOR_BODY:%.*]] ], [ [[STR_PH_0]], [[FOR_INC_PREHEADER]] ] 60; V8A-NEXT: [[INCDEC_PTR109]] = getelementptr inbounds i8, i8* [[STR_PH_1]], i32 1 61; V8A-NEXT: [[LOAD_1:%.*]] = load i8, i8* [[INCDEC_PTR109]], align 1 62; V8A-NEXT: [[TOBOOL:%.*]] = icmp ne i8 [[LOAD_1]], 0 63; V8A-NEXT: [[AND:%.*]] = and i1 [[CMP]], [[TOBOOL]] 64; V8A-NEXT: br i1 [[AND]], label [[FOR_BODY]], label [[EXIT:%.*]] 65; V8A: for.body: 66; V8A-NEXT: [[CMP_1:%.*]] = icmp eq i8 [[LOAD_1]], 1 67; V8A-NEXT: br i1 [[CMP_1]], label [[FOR_INC]], label [[SW_BB92]] 68; V8A: exit: 69; V8A-NEXT: ret i32 [[PHI_RES]] 70; 71entry: 72 %gep.a.2 = getelementptr inbounds i8, i8* %a, i32 2 73 %incdec.ptr109.c4 = getelementptr inbounds i8, i8* %a, i32 3 74 %zero = icmp ne i8 %in, 0 75 br i1 %zero , label %for.inc.preheader, label %sw.bb92 76 77sw.bb92: 78 %c.off.i150 = add i8 %in, -48 79 %ugt.9 = icmp ugt i8 %c.off.i150, 9 80 br i1 %ugt.9, label %for.inc.preheader, label %select.unfold198 81 82select.unfold198: 83 br label %for.inc.preheader 84 85for.inc.preheader: 86 %str.ph.0 = phi i8* [ %incdec.ptr109.c4, %select.unfold198 ], [ %incdec.ptr109.c4, %sw.bb92 ], [ %gep.a.2, %entry ] 87 %cmp = phi i1 [ true, %select.unfold198 ], [ false, %sw.bb92 ], [ false, %entry ] 88 %phi.res = phi i32 [ 7, %select.unfold198 ], [ 1, %sw.bb92 ], [ 1, %entry ] 89 br label %for.inc 90 91for.inc: 92 %str.ph.1 = phi i8* [ %incdec.ptr109, %for.body ], [ %str.ph.0, %for.inc.preheader ] 93 %incdec.ptr109 = getelementptr inbounds i8, i8* %str.ph.1, i32 1 94 %load.1 = load i8, i8* %incdec.ptr109, align 1 95 %tobool = icmp ne i8 %load.1, 0 96 %and = and i1 %cmp, %tobool 97 br i1 %and, label %for.body, label %exit 98 99for.body: 100 %cmp.1 = icmp eq i8 %load.1, 1 101 br i1 %cmp.1, label %for.inc, label %sw.bb92 102 103exit: 104 ret i32 %phi.res 105} 106 107define i32 @multiple_spec_select_costs_minsize(i8* %a, i32* %idx, i8 %in) #0 { 108; V8M-LABEL: @multiple_spec_select_costs_minsize( 109; V8M-NEXT: entry: 110; V8M-NEXT: [[GEP_A_2:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i32 2 111; V8M-NEXT: [[INCDEC_PTR109_C4:%.*]] = getelementptr inbounds i8, i8* [[A]], i32 3 112; V8M-NEXT: [[ZERO:%.*]] = icmp ne i8 [[IN:%.*]], 0 113; V8M-NEXT: br i1 [[ZERO]], label [[FOR_INC_PREHEADER:%.*]], label [[SW_BB92:%.*]] 114; V8M: sw.bb92: 115; V8M-NEXT: [[C_OFF_I150:%.*]] = add i8 [[IN]], -48 116; V8M-NEXT: [[UGT_9:%.*]] = icmp ugt i8 [[C_OFF_I150]], 9 117; V8M-NEXT: br i1 [[UGT_9]], label [[FOR_INC_PREHEADER]], label [[SELECT_UNFOLD198:%.*]] 118; V8M: select.unfold198: 119; V8M-NEXT: br label [[FOR_INC_PREHEADER]] 120; V8M: for.inc.preheader: 121; V8M-NEXT: [[STR_PH_0:%.*]] = phi i8* [ [[INCDEC_PTR109_C4]], [[SELECT_UNFOLD198]] ], [ [[INCDEC_PTR109_C4]], [[SW_BB92]] ], [ [[GEP_A_2]], [[ENTRY:%.*]] ] 122; V8M-NEXT: [[CMP:%.*]] = phi i1 [ true, [[SELECT_UNFOLD198]] ], [ false, [[SW_BB92]] ], [ false, [[ENTRY]] ] 123; V8M-NEXT: [[PHI_RES:%.*]] = phi i32 [ 7, [[SELECT_UNFOLD198]] ], [ 1, [[SW_BB92]] ], [ 1, [[ENTRY]] ] 124; V8M-NEXT: br label [[FOR_INC:%.*]] 125; V8M: for.inc: 126; V8M-NEXT: [[STR_PH_1:%.*]] = phi i8* [ [[INCDEC_PTR109:%.*]], [[FOR_BODY:%.*]] ], [ [[STR_PH_0]], [[FOR_INC_PREHEADER]] ] 127; V8M-NEXT: [[INCDEC_PTR109]] = getelementptr inbounds i8, i8* [[STR_PH_1]], i32 1 128; V8M-NEXT: [[LOAD_1:%.*]] = load i8, i8* [[INCDEC_PTR109]], align 1 129; V8M-NEXT: [[TOBOOL:%.*]] = icmp ne i8 [[LOAD_1]], 0 130; V8M-NEXT: [[AND:%.*]] = and i1 [[CMP]], [[TOBOOL]] 131; V8M-NEXT: br i1 [[AND]], label [[FOR_BODY]], label [[EXIT:%.*]] 132; V8M: for.body: 133; V8M-NEXT: [[CMP_1:%.*]] = icmp eq i8 [[LOAD_1]], 1 134; V8M-NEXT: br i1 [[CMP_1]], label [[FOR_INC]], label [[SW_BB92]] 135; V8M: exit: 136; V8M-NEXT: ret i32 [[PHI_RES]] 137; 138; V8A-LABEL: @multiple_spec_select_costs_minsize( 139; V8A-NEXT: entry: 140; V8A-NEXT: [[GEP_A_2:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i32 2 141; V8A-NEXT: [[INCDEC_PTR109_C4:%.*]] = getelementptr inbounds i8, i8* [[A]], i32 3 142; V8A-NEXT: [[ZERO:%.*]] = icmp ne i8 [[IN:%.*]], 0 143; V8A-NEXT: br i1 [[ZERO]], label [[FOR_INC_PREHEADER:%.*]], label [[SW_BB92:%.*]] 144; V8A: sw.bb92: 145; V8A-NEXT: [[C_OFF_I150:%.*]] = add i8 [[IN]], -48 146; V8A-NEXT: [[UGT_9:%.*]] = icmp ugt i8 [[C_OFF_I150]], 9 147; V8A-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[UGT_9]], i1 false, i1 true 148; V8A-NEXT: [[SPEC_SELECT1:%.*]] = select i1 [[UGT_9]], i32 1, i32 7 149; V8A-NEXT: br label [[FOR_INC_PREHEADER]] 150; V8A: for.inc.preheader: 151; V8A-NEXT: [[STR_PH_0:%.*]] = phi i8* [ [[GEP_A_2]], [[ENTRY:%.*]] ], [ [[INCDEC_PTR109_C4]], [[SW_BB92]] ] 152; V8A-NEXT: [[CMP:%.*]] = phi i1 [ false, [[ENTRY]] ], [ [[SPEC_SELECT]], [[SW_BB92]] ] 153; V8A-NEXT: [[PHI_RES:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ [[SPEC_SELECT1]], [[SW_BB92]] ] 154; V8A-NEXT: br label [[FOR_INC:%.*]] 155; V8A: for.inc: 156; V8A-NEXT: [[STR_PH_1:%.*]] = phi i8* [ [[INCDEC_PTR109:%.*]], [[FOR_BODY:%.*]] ], [ [[STR_PH_0]], [[FOR_INC_PREHEADER]] ] 157; V8A-NEXT: [[INCDEC_PTR109]] = getelementptr inbounds i8, i8* [[STR_PH_1]], i32 1 158; V8A-NEXT: [[LOAD_1:%.*]] = load i8, i8* [[INCDEC_PTR109]], align 1 159; V8A-NEXT: [[TOBOOL:%.*]] = icmp ne i8 [[LOAD_1]], 0 160; V8A-NEXT: [[AND:%.*]] = and i1 [[CMP]], [[TOBOOL]] 161; V8A-NEXT: br i1 [[AND]], label [[FOR_BODY]], label [[EXIT:%.*]] 162; V8A: for.body: 163; V8A-NEXT: [[CMP_1:%.*]] = icmp eq i8 [[LOAD_1]], 1 164; V8A-NEXT: br i1 [[CMP_1]], label [[FOR_INC]], label [[SW_BB92]] 165; V8A: exit: 166; V8A-NEXT: ret i32 [[PHI_RES]] 167; 168entry: 169 %gep.a.2 = getelementptr inbounds i8, i8* %a, i32 2 170 %incdec.ptr109.c4 = getelementptr inbounds i8, i8* %a, i32 3 171 %zero = icmp ne i8 %in, 0 172 br i1 %zero , label %for.inc.preheader, label %sw.bb92 173 174sw.bb92: 175 %c.off.i150 = add i8 %in, -48 176 %ugt.9 = icmp ugt i8 %c.off.i150, 9 177 br i1 %ugt.9, label %for.inc.preheader, label %select.unfold198 178 179select.unfold198: 180 br label %for.inc.preheader 181 182for.inc.preheader: 183 %str.ph.0 = phi i8* [ %incdec.ptr109.c4, %select.unfold198 ], [ %incdec.ptr109.c4, %sw.bb92 ], [ %gep.a.2, %entry ] 184 %cmp = phi i1 [ true, %select.unfold198 ], [ false, %sw.bb92 ], [ false, %entry ] 185 %phi.res = phi i32 [ 7, %select.unfold198 ], [ 1, %sw.bb92 ], [ 1, %entry ] 186 br label %for.inc 187 188for.inc: 189 %str.ph.1 = phi i8* [ %incdec.ptr109, %for.body ], [ %str.ph.0, %for.inc.preheader ] 190 %incdec.ptr109 = getelementptr inbounds i8, i8* %str.ph.1, i32 1 191 %load.1 = load i8, i8* %incdec.ptr109, align 1 192 %tobool = icmp ne i8 %load.1, 0 193 %and = and i1 %cmp, %tobool 194 br i1 %and, label %for.body, label %exit 195 196for.body: 197 %cmp.1 = icmp eq i8 %load.1, 1 198 br i1 %cmp.1, label %for.inc, label %sw.bb92 199 200exit: 201 ret i32 %phi.res 202} 203 204attributes #0 = { minsize optsize } 205