1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -instcombine < %s | FileCheck %s 3 4declare void @use(i8) 5declare void @use.i1(i1) 6declare i8 @llvm.umin.i8(i8, i8) 7 8define i1 @icmp_select_const(i8 %x, i8 %y) { 9; CHECK-LABEL: @icmp_select_const( 10; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 11; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], 0 12; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 13; CHECK-NEXT: ret i1 [[CMP2]] 14; 15 %cmp1 = icmp eq i8 %x, 0 16 %sel = select i1 %cmp1, i8 0, i8 %y 17 %cmp2 = icmp eq i8 %sel, 0 18 ret i1 %cmp2 19} 20 21define i1 @icmp_select_var(i8 %x, i8 %y, i8 %z) { 22; CHECK-LABEL: @icmp_select_var( 23; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 24; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[Z:%.*]] 25; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 26; CHECK-NEXT: ret i1 [[CMP2]] 27; 28 %cmp1 = icmp eq i8 %x, 0 29 %sel = select i1 %cmp1, i8 %z, i8 %y 30 %cmp2 = icmp eq i8 %sel, %z 31 ret i1 %cmp2 32} 33 34define i1 @icmp_select_var_commuted(i8 %x, i8 %y, i8 %_z) { 35; CHECK-LABEL: @icmp_select_var_commuted( 36; CHECK-NEXT: [[Z:%.*]] = udiv i8 42, [[_Z:%.*]] 37; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 38; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Z]], [[Y:%.*]] 39; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 40; CHECK-NEXT: ret i1 [[CMP2]] 41; 42 %z = udiv i8 42, %_z ; thwart complexity-based canonicalization 43 %cmp1 = icmp eq i8 %x, 0 44 %sel = select i1 %cmp1, i8 %z, i8 %y 45 %cmp2 = icmp eq i8 %z, %sel 46 ret i1 %cmp2 47} 48 49define i1 @icmp_select_var_select(i8 %x, i8 %y, i1 %c) { 50; CHECK-LABEL: @icmp_select_var_select( 51; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 52; CHECK-NEXT: [[CMP212:%.*]] = icmp eq i8 [[X]], [[Y:%.*]] 53; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true 54; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[CMP1]], i1 true, i1 [[NOT_C]] 55; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[CMP212]] 56; CHECK-NEXT: ret i1 [[CMP2]] 57; 58 %z = select i1 %c, i8 %x, i8 %y 59 %cmp1 = icmp eq i8 %x, 0 60 %sel = select i1 %cmp1, i8 %z, i8 %y 61 %cmp2 = icmp eq i8 %z, %sel 62 ret i1 %cmp2 63} 64 65define i1 @icmp_select_var_both_fold(i8 %x, i8 %y, i8 %_z) { 66; CHECK-LABEL: @icmp_select_var_both_fold( 67; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 68; CHECK-NEXT: ret i1 [[CMP1]] 69; 70 %z = or i8 %_z, 1 71 %cmp1 = icmp eq i8 %x, 0 72 %sel = select i1 %cmp1, i8 %z, i8 2 73 %cmp2 = icmp eq i8 %sel, %z 74 ret i1 %cmp2 75} 76 77define i1 @icmp_select_var_extra_use(i8 %x, i8 %y, i8 %z) { 78; CHECK-LABEL: @icmp_select_var_extra_use( 79; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 80; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 [[Z:%.*]], i8 [[Y:%.*]] 81; CHECK-NEXT: call void @use(i8 [[SEL]]) 82; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[SEL]], [[Z]] 83; CHECK-NEXT: ret i1 [[CMP2]] 84; 85 %cmp1 = icmp eq i8 %x, 0 86 %sel = select i1 %cmp1, i8 %z, i8 %y 87 call void @use(i8 %sel) 88 %cmp2 = icmp eq i8 %sel, %z 89 ret i1 %cmp2 90} 91 92define i1 @icmp_select_var_both_fold_extra_use(i8 %x, i8 %y, i8 %_z) { 93; CHECK-LABEL: @icmp_select_var_both_fold_extra_use( 94; CHECK-NEXT: [[Z:%.*]] = or i8 [[_Z:%.*]], 1 95; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 96; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 [[Z]], i8 2 97; CHECK-NEXT: call void @use(i8 [[SEL]]) 98; CHECK-NEXT: ret i1 [[CMP1]] 99; 100 %z = or i8 %_z, 1 101 %cmp1 = icmp eq i8 %x, 0 102 %sel = select i1 %cmp1, i8 %z, i8 2 103 call void @use(i8 %sel) 104 %cmp2 = icmp eq i8 %sel, %z 105 ret i1 %cmp2 106} 107 108define i1 @icmp_select_var_pred_ne(i8 %x, i8 %y, i8 %z) { 109; CHECK-LABEL: @icmp_select_var_pred_ne( 110; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0 111; CHECK-NEXT: [[CMP21:%.*]] = icmp ne i8 [[Y:%.*]], [[Z:%.*]] 112; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false 113; CHECK-NEXT: ret i1 [[CMP2]] 114; 115 %cmp1 = icmp eq i8 %x, 0 116 %sel = select i1 %cmp1, i8 %z, i8 %y 117 %cmp2 = icmp ne i8 %sel, %z 118 ret i1 %cmp2 119} 120 121define i1 @icmp_select_var_pred_ult(i8 %x, i8 %y, i8 %z) { 122; CHECK-LABEL: @icmp_select_var_pred_ult( 123; CHECK-NEXT: [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2 124; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 125; CHECK-NEXT: [[CMP21:%.*]] = icmp ugt i8 [[Z1]], [[Y:%.*]] 126; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 127; CHECK-NEXT: ret i1 [[CMP2]] 128; 129 %z1 = add nuw i8 %z, 2 130 %cmp1 = icmp eq i8 %x, 0 131 %sel = select i1 %cmp1, i8 %z, i8 %y 132 %cmp2 = icmp ult i8 %sel, %z1 133 ret i1 %cmp2 134} 135 136define i1 @icmp_select_var_pred_uge(i8 %x, i8 %y, i8 %z) { 137; CHECK-LABEL: @icmp_select_var_pred_uge( 138; CHECK-NEXT: [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2 139; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0 140; CHECK-NEXT: [[CMP21:%.*]] = icmp ule i8 [[Z1]], [[Y:%.*]] 141; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false 142; CHECK-NEXT: ret i1 [[CMP2]] 143; 144 %z1 = add nuw i8 %z, 2 145 %cmp1 = icmp eq i8 %x, 0 146 %sel = select i1 %cmp1, i8 %z, i8 %y 147 %cmp2 = icmp uge i8 %sel, %z1 148 ret i1 %cmp2 149} 150 151define i1 @icmp_select_var_pred_uge_commuted(i8 %x, i8 %y, i8 %z) { 152; CHECK-LABEL: @icmp_select_var_pred_uge_commuted( 153; CHECK-NEXT: [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2 154; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 155; CHECK-NEXT: [[CMP21:%.*]] = icmp uge i8 [[Z1]], [[Y:%.*]] 156; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 157; CHECK-NEXT: ret i1 [[CMP2]] 158; 159 %z1 = add nuw i8 %z, 2 160 %cmp1 = icmp eq i8 %x, 0 161 %sel = select i1 %cmp1, i8 %z, i8 %y 162 %cmp2 = icmp uge i8 %z1, %sel 163 ret i1 %cmp2 164} 165 166define i1 @icmp_select_implied_cond(i8 %x, i8 %y) { 167; CHECK-LABEL: @icmp_select_implied_cond( 168; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 169; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[X]] 170; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 171; CHECK-NEXT: ret i1 [[CMP2]] 172; 173 %cmp1 = icmp eq i8 %x, 0 174 %sel = select i1 %cmp1, i8 0, i8 %y 175 %cmp2 = icmp eq i8 %sel, %x 176 ret i1 %cmp2 177} 178 179define i1 @icmp_select_implied_cond_ne(i8 %x, i8 %y) { 180; CHECK-LABEL: @icmp_select_implied_cond_ne( 181; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0 182; CHECK-NEXT: [[CMP21:%.*]] = icmp ne i8 [[Y:%.*]], [[X]] 183; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false 184; CHECK-NEXT: ret i1 [[CMP2]] 185; 186 %cmp1 = icmp eq i8 %x, 0 187 %sel = select i1 %cmp1, i8 0, i8 %y 188 %cmp2 = icmp ne i8 %sel, %x 189 ret i1 %cmp2 190} 191 192define i1 @icmp_select_implied_cond_swapped_select(i8 %x, i8 %y) { 193; CHECK-LABEL: @icmp_select_implied_cond_swapped_select( 194; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 195; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], 0 196; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false 197; CHECK-NEXT: ret i1 [[CMP2]] 198; 199 %cmp1 = icmp eq i8 %x, 0 200 %sel = select i1 %cmp1, i8 %y, i8 0 201 %cmp2 = icmp eq i8 %sel, %x 202 ret i1 %cmp2 203} 204 205define i1 @icmp_select_implied_cond_swapped_select_with_inv_cond(i8 %x, i8 %y) { 206; CHECK-LABEL: @icmp_select_implied_cond_swapped_select_with_inv_cond( 207; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0 208; CHECK-NEXT: call void @use.i1(i1 [[CMP1]]) 209; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[X]] 210; CHECK-NEXT: [[NOT_CMP1:%.*]] = xor i1 [[CMP1]], true 211; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[NOT_CMP1]], i1 true, i1 [[CMP21]] 212; CHECK-NEXT: ret i1 [[CMP2]] 213; 214 %cmp1 = icmp ne i8 %x, 0 215 call void @use.i1(i1 %cmp1) 216 %sel = select i1 %cmp1, i8 %y, i8 0 217 %cmp2 = icmp eq i8 %sel, %x 218 ret i1 %cmp2 219} 220 221define i1 @icmp_select_implied_cond_relational(i8 %x, i8 %y) { 222; CHECK-LABEL: @icmp_select_implied_cond_relational( 223; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 [[X:%.*]], 10 224; CHECK-NEXT: [[CMP21:%.*]] = icmp ult i8 [[Y:%.*]], [[X]] 225; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 226; CHECK-NEXT: ret i1 [[CMP2]] 227; 228 %cmp1 = icmp ugt i8 %x, 10 229 %sel = select i1 %cmp1, i8 10, i8 %y 230 %cmp2 = icmp ult i8 %sel, %x 231 ret i1 %cmp2 232} 233 234define i1 @icmp_select_implied_cond_relational_off_by_one(i8 %x, i8 %y) { 235; CHECK-LABEL: @icmp_select_implied_cond_relational_off_by_one( 236; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 [[X:%.*]], 10 237; CHECK-NEXT: call void @use.i1(i1 [[CMP1]]) 238; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 11, i8 [[Y:%.*]] 239; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 [[SEL]], [[X]] 240; CHECK-NEXT: ret i1 [[CMP2]] 241; 242 %cmp1 = icmp ugt i8 %x, 10 243 call void @use.i1(i1 %cmp1) 244 %sel = select i1 %cmp1, i8 11, i8 %y 245 %cmp2 = icmp ult i8 %sel, %x 246 ret i1 %cmp2 247} 248 249define i1 @umin_seq_comparison(i8 %x, i8 %y) { 250; CHECK-LABEL: @umin_seq_comparison( 251; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 252; CHECK-NEXT: [[CMP21:%.*]] = icmp ule i8 [[X]], [[Y:%.*]] 253; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 254; CHECK-NEXT: ret i1 [[CMP2]] 255; 256 %min = call i8 @llvm.umin.i8(i8 %x, i8 %y) 257 %cmp1 = icmp eq i8 %x, 0 258 %sel = select i1 %cmp1, i8 0, i8 %min 259 %cmp2 = icmp eq i8 %sel, %x 260 ret i1 %cmp2 261} 262