1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4define i32 @max_na_b_minux_na(i32 %A, i32 %B) { 5; CHECK-LABEL: @max_na_b_minux_na( 6; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A:%.*]], -1 7; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]]) 8; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]] 9; CHECK-NEXT: ret i32 [[TMP2]] 10; 11 %not = xor i32 %A, -1 12 %l0 = icmp ult i32 %not, %B 13 %l1 = select i1 %l0, i32 %not, i32 %B 14 %x = sub i32 %l1, %not 15 ret i32 %x 16} 17 18define i32 @na_minus_max_na_b(i32 %A, i32 %B) { 19; CHECK-LABEL: @na_minus_max_na_b( 20; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A:%.*]], -1 21; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]]) 22; CHECK-NEXT: ret i32 [[TMP1]] 23; 24 %not = xor i32 %A, -1 25 %l0 = icmp ult i32 %not, %B 26 %l1 = select i1 %l0, i32 %not, i32 %B 27 %x = sub i32 %not, %l1 28 ret i32 %x 29} 30 31define i32 @max_b_na_minus_na(i32 %A, i32 %B) { 32; CHECK-LABEL: @max_b_na_minus_na( 33; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A:%.*]], -1 34; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]]) 35; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]] 36; CHECK-NEXT: ret i32 [[TMP2]] 37; 38 %not = xor i32 %A, -1 39 %l0 = icmp ugt i32 %not, %B 40 %l1 = select i1 %l0, i32 %B, i32 %not 41 %x = sub i32 %l1, %not 42 ret i32 %x 43} 44 45define i32 @na_minus_max_b_na(i32 %A, i32 %B) { 46; CHECK-LABEL: @na_minus_max_b_na( 47; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A:%.*]], -1 48; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[NOT]], i32 [[B:%.*]]) 49; CHECK-NEXT: ret i32 [[TMP1]] 50; 51 %not = xor i32 %A, -1 52 %l0 = icmp ugt i32 %not, %B 53 %l1 = select i1 %l0, i32 %B, i32 %not 54 %x = sub i32 %not, %l1 55 ret i32 %x 56} 57 58 59define i32 @max_na_bi_minux_na(i32 %A, i32 %Bi) { 60; CHECK-LABEL: @max_na_bi_minux_na( 61; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]]) 62; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]] 63; CHECK-NEXT: ret i32 [[TMP2]] 64; 65 %B = xor i32 %Bi, -1 66 %not = xor i32 %A, -1 67 %l0 = icmp ult i32 %not, %B 68 %l1 = select i1 %l0, i32 %not, i32 %B 69 %x = sub i32 %l1, %not 70 ret i32 %x 71} 72 73define i32 @na_minus_max_na_bi(i32 %A, i32 %Bi) { 74; CHECK-LABEL: @na_minus_max_na_bi( 75; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]]) 76; CHECK-NEXT: ret i32 [[TMP1]] 77; 78 %B = xor i32 %Bi, -1 79 %not = xor i32 %A, -1 80 %l0 = icmp ult i32 %not, %B 81 %l1 = select i1 %l0, i32 %not, i32 %B 82 %x = sub i32 %not, %l1 83 ret i32 %x 84} 85 86define i32 @max_bi_na_minus_na(i32 %A, i32 %Bi) { 87; CHECK-LABEL: @max_bi_na_minus_na( 88; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]]) 89; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]] 90; CHECK-NEXT: ret i32 [[TMP2]] 91; 92 %B = xor i32 %Bi, -1 93 %not = xor i32 %A, -1 94 %l0 = icmp ugt i32 %not, %B 95 %l1 = select i1 %l0, i32 %B, i32 %not 96 %x = sub i32 %l1, %not 97 ret i32 %x 98} 99 100define i32 @na_minus_max_bi_na(i32 %A, i32 %Bi) { 101; CHECK-LABEL: @na_minus_max_bi_na( 102; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[BI:%.*]], i32 [[A:%.*]]) 103; CHECK-NEXT: ret i32 [[TMP1]] 104; 105 %B = xor i32 %Bi, -1 106 %not = xor i32 %A, -1 107 %l0 = icmp ugt i32 %not, %B 108 %l1 = select i1 %l0, i32 %B, i32 %not 109 %x = sub i32 %not, %l1 110 ret i32 %x 111} 112 113 114define i32 @max_na_bi_minux_na_use(i32 %A, i32 %Bi) { 115; CHECK-LABEL: @max_na_bi_minux_na_use( 116; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A:%.*]], -32 117; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[A]], i32 -32 118; CHECK-NEXT: [[L1:%.*]] = xor i32 [[TMP2]], -1 119; CHECK-NEXT: [[X:%.*]] = sub i32 [[A]], [[TMP2]] 120; CHECK-NEXT: call void @use32(i32 [[L1]]) 121; CHECK-NEXT: ret i32 [[X]] 122; 123 %not = xor i32 %A, -1 124 %l0 = icmp ult i32 %not, 31 125 %l1 = select i1 %l0, i32 %not, i32 31 126 %x = sub i32 %l1, %not 127 call void @use32(i32 %l1) 128 ret i32 %x 129} 130 131define i32 @na_minus_max_na_bi_use(i32 %A, i32 %Bi) { 132; CHECK-LABEL: @na_minus_max_na_bi_use( 133; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[A:%.*]], -32 134; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[A]], i32 -32 135; CHECK-NEXT: [[L1:%.*]] = xor i32 [[TMP2]], -1 136; CHECK-NEXT: [[X:%.*]] = sub i32 [[TMP2]], [[A]] 137; CHECK-NEXT: call void @use32(i32 [[L1]]) 138; CHECK-NEXT: ret i32 [[X]] 139; 140 %not = xor i32 %A, -1 141 %l0 = icmp ult i32 %not, 31 142 %l1 = select i1 %l0, i32 %not, i32 31 143 %x = sub i32 %not, %l1 144 call void @use32(i32 %l1) 145 ret i32 %x 146} 147 148define i32 @max_bi_na_minus_na_use(i32 %A, i32 %Bi) { 149; CHECK-LABEL: @max_bi_na_minus_na_use( 150; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[BI:%.*]], [[A:%.*]] 151; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]] 152; CHECK-NEXT: [[L1:%.*]] = xor i32 [[TMP2]], -1 153; CHECK-NEXT: [[X:%.*]] = sub i32 [[A]], [[TMP2]] 154; CHECK-NEXT: call void @use32(i32 [[L1]]) 155; CHECK-NEXT: ret i32 [[X]] 156; 157 %not = xor i32 %A, -1 158 %B = xor i32 %Bi, -1 159 %l0 = icmp ult i32 %B, %not 160 %l1 = select i1 %l0, i32 %B, i32 %not 161 %x = sub i32 %l1, %not 162 call void @use32(i32 %l1) 163 ret i32 %x 164} 165 166define i32 @na_minus_max_bi_na_use(i32 %A, i32 %Bi) { 167; CHECK-LABEL: @na_minus_max_bi_na_use( 168; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[BI:%.*]], [[A:%.*]] 169; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]] 170; CHECK-NEXT: [[L1:%.*]] = xor i32 [[TMP2]], -1 171; CHECK-NEXT: [[X:%.*]] = sub i32 [[TMP2]], [[A]] 172; CHECK-NEXT: call void @use32(i32 [[L1]]) 173; CHECK-NEXT: ret i32 [[X]] 174; 175 %not = xor i32 %A, -1 176 %B = xor i32 %Bi, -1 177 %l0 = icmp ult i32 %B, %not 178 %l1 = select i1 %l0, i32 %B, i32 %not 179 %x = sub i32 %not, %l1 180 call void @use32(i32 %l1) 181 ret i32 %x 182} 183 184 185define i32 @max_na_bi_minux_na_use2(i32 %A, i32 %Bi) { 186; CHECK-LABEL: @max_na_bi_minux_na_use2( 187; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A:%.*]], -1 188; CHECK-NEXT: [[L0:%.*]] = icmp ult i32 [[NOT]], 31 189; CHECK-NEXT: [[L1:%.*]] = select i1 [[L0]], i32 [[NOT]], i32 31 190; CHECK-NEXT: [[X:%.*]] = sub i32 [[L1]], [[NOT]] 191; CHECK-NEXT: call void @use32(i32 [[L1]]) 192; CHECK-NEXT: call void @use32(i32 [[NOT]]) 193; CHECK-NEXT: ret i32 [[X]] 194; 195 %not = xor i32 %A, -1 196 %l0 = icmp ult i32 %not, 31 197 %l1 = select i1 %l0, i32 %not, i32 31 198 %x = sub i32 %l1, %not 199 call void @use32(i32 %l1) 200 call void @use32(i32 %not) 201 ret i32 %x 202} 203 204define i32 @na_minus_max_na_bi_use2(i32 %A, i32 %Bi) { 205; CHECK-LABEL: @na_minus_max_na_bi_use2( 206; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A:%.*]], -1 207; CHECK-NEXT: [[L0:%.*]] = icmp ult i32 [[NOT]], 31 208; CHECK-NEXT: [[L1:%.*]] = select i1 [[L0]], i32 [[NOT]], i32 31 209; CHECK-NEXT: [[X:%.*]] = sub i32 [[NOT]], [[L1]] 210; CHECK-NEXT: call void @use32(i32 [[L1]]) 211; CHECK-NEXT: call void @use32(i32 [[NOT]]) 212; CHECK-NEXT: ret i32 [[X]] 213; 214 %not = xor i32 %A, -1 215 %l0 = icmp ult i32 %not, 31 216 %l1 = select i1 %l0, i32 %not, i32 31 217 %x = sub i32 %not, %l1 218 call void @use32(i32 %l1) 219 call void @use32(i32 %not) 220 ret i32 %x 221} 222 223define i32 @max_bi_na_minus_na_use2(i32 %A, i32 %Bi) { 224; CHECK-LABEL: @max_bi_na_minus_na_use2( 225; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A:%.*]], -1 226; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[BI:%.*]], [[A]] 227; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]] 228; CHECK-NEXT: [[L1:%.*]] = xor i32 [[TMP2]], -1 229; CHECK-NEXT: [[X:%.*]] = sub i32 [[A]], [[TMP2]] 230; CHECK-NEXT: call void @use32(i32 [[L1]]) 231; CHECK-NEXT: call void @use32(i32 [[NOT]]) 232; CHECK-NEXT: ret i32 [[X]] 233; 234 %not = xor i32 %A, -1 235 %B = xor i32 %Bi, -1 236 %l0 = icmp ult i32 %B, %not 237 %l1 = select i1 %l0, i32 %B, i32 %not 238 %x = sub i32 %l1, %not 239 call void @use32(i32 %l1) 240 call void @use32(i32 %not) 241 ret i32 %x 242} 243 244define i32 @na_minus_max_bi_na_use2(i32 %A, i32 %Bi) { 245; CHECK-LABEL: @na_minus_max_bi_na_use2( 246; CHECK-NEXT: [[NOT:%.*]] = xor i32 [[A:%.*]], -1 247; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[BI:%.*]], [[A]] 248; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[BI]], i32 [[A]] 249; CHECK-NEXT: [[L1:%.*]] = xor i32 [[TMP2]], -1 250; CHECK-NEXT: [[X:%.*]] = sub i32 [[TMP2]], [[A]] 251; CHECK-NEXT: call void @use32(i32 [[L1]]) 252; CHECK-NEXT: call void @use32(i32 [[NOT]]) 253; CHECK-NEXT: ret i32 [[X]] 254; 255 %not = xor i32 %A, -1 256 %B = xor i32 %Bi, -1 257 %l0 = icmp ult i32 %B, %not 258 %l1 = select i1 %l0, i32 %B, i32 %not 259 %x = sub i32 %not, %l1 260 call void @use32(i32 %l1) 261 call void @use32(i32 %not) 262 ret i32 %x 263} 264 265define i8 @umin_not_sub(i8 %x, i8 %y) { 266; CHECK-LABEL: @umin_not_sub( 267; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]] 268; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Y]] 269; CHECK-NEXT: [[MINXY:%.*]] = xor i8 [[TMP2]], -1 270; CHECK-NEXT: [[SUBX:%.*]] = sub i8 [[TMP2]], [[X]] 271; CHECK-NEXT: [[SUBY:%.*]] = sub i8 [[TMP2]], [[Y]] 272; CHECK-NEXT: call void @use8(i8 [[SUBX]]) 273; CHECK-NEXT: call void @use8(i8 [[SUBY]]) 274; CHECK-NEXT: ret i8 [[MINXY]] 275; 276 %nx = xor i8 %x, -1 277 %ny = xor i8 %y, -1 278 %cmpxy = icmp ult i8 %nx, %ny 279 %minxy = select i1 %cmpxy, i8 %nx, i8 %ny 280 %subx = sub i8 %nx, %minxy 281 %suby = sub i8 %ny, %minxy 282 call void @use8(i8 %subx) 283 call void @use8(i8 %suby) 284 ret i8 %minxy 285} 286 287define i8 @umin_not_sub_rev(i8 %x, i8 %y) { 288; CHECK-LABEL: @umin_not_sub_rev( 289; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]] 290; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Y]] 291; CHECK-NEXT: [[MINXY:%.*]] = xor i8 [[TMP2]], -1 292; CHECK-NEXT: [[SUBX:%.*]] = sub i8 [[X]], [[TMP2]] 293; CHECK-NEXT: [[SUBY:%.*]] = sub i8 [[Y]], [[TMP2]] 294; CHECK-NEXT: call void @use8(i8 [[SUBX]]) 295; CHECK-NEXT: call void @use8(i8 [[SUBY]]) 296; CHECK-NEXT: ret i8 [[MINXY]] 297; 298 %nx = xor i8 %x, -1 299 %ny = xor i8 %y, -1 300 %cmpxy = icmp ult i8 %nx, %ny 301 %minxy = select i1 %cmpxy, i8 %nx, i8 %ny 302 %subx = sub i8 %minxy, %nx 303 %suby = sub i8 %minxy, %ny 304 call void @use8(i8 %subx) 305 call void @use8(i8 %suby) 306 ret i8 %minxy 307} 308 309define void @umin3_not_all_ops_extra_uses_invert_subs(i8 %x, i8 %y, i8 %z) { 310; CHECK-LABEL: @umin3_not_all_ops_extra_uses_invert_subs( 311; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], [[Z:%.*]] 312; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 [[Z]] 313; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt i8 [[TMP2]], [[Y:%.*]] 314; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i8 [[TMP2]], i8 [[Y]] 315; CHECK-NEXT: [[TMP5:%.*]] = xor i8 [[TMP4]], -1 316; CHECK-NEXT: [[XMIN:%.*]] = sub i8 [[TMP4]], [[X]] 317; CHECK-NEXT: [[YMIN:%.*]] = sub i8 [[TMP4]], [[Y]] 318; CHECK-NEXT: [[ZMIN:%.*]] = sub i8 [[TMP4]], [[Z]] 319; CHECK-NEXT: call void @use8(i8 [[TMP5]]) 320; CHECK-NEXT: call void @use8(i8 [[XMIN]]) 321; CHECK-NEXT: call void @use8(i8 [[YMIN]]) 322; CHECK-NEXT: call void @use8(i8 [[ZMIN]]) 323; CHECK-NEXT: ret void 324; 325 %xn = xor i8 %x, -1 326 %yn = xor i8 %y, -1 327 %zn = xor i8 %z, -1 328 %cmpxz = icmp ult i8 %xn, %zn 329 %minxz = select i1 %cmpxz, i8 %xn, i8 %zn 330 %cmpxyz = icmp ult i8 %minxz, %yn 331 %minxyz = select i1 %cmpxyz, i8 %minxz, i8 %yn 332 %xmin = sub i8 %xn, %minxyz 333 %ymin = sub i8 %yn, %minxyz 334 %zmin = sub i8 %zn, %minxyz 335 call void @use8(i8 %minxyz) 336 call void @use8(i8 %xmin) 337 call void @use8(i8 %ymin) 338 call void @use8(i8 %zmin) 339 ret void 340} 341 342declare void @use8(i8) 343declare void @use32(i32 %u) 344