1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare i8 @llvm.smin.i8(i8, i8) 5declare i8 @llvm.umin.i8(i8, i8) 6declare i8 @llvm.smax.i8(i8, i8) 7declare i8 @llvm.umax.i8(i8, i8) 8 9declare void @llvm.assume(i1) 10 11declare void @use.i8(i8) 12declare void @use.i1(i1) 13 14define i8 @xor_1(i8 %a, i1 %c, i8 %x, i8 %y) { 15; CHECK-LABEL: @xor_1( 16; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124 17; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]] 18; CHECK-NEXT: [[NOT_BA:%.*]] = xor i8 [[TMP2]], [[A:%.*]] 19; CHECK-NEXT: ret i8 [[NOT_BA]] 20; 21 %nx = xor i8 %x, -1 22 %yy = xor i8 %y, 123 23 %b = select i1 %c, i8 %nx, i8 %yy 24 %ba = xor i8 %b, %a 25 %not_ba = xor i8 %ba, -1 26 ret i8 %not_ba 27} 28 29define i8 @xor_2(i8 %a, i1 %c, i8 %x, i8 %y) { 30; CHECK-LABEL: @xor_2( 31; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124 32; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]] 33; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[A:%.*]], [[TMP2]] 34; CHECK-NEXT: ret i8 [[NOT_AB]] 35; 36 %nx = xor i8 %x, -1 37 %yy = xor i8 %y, 123 38 %b = select i1 %c, i8 %nx, i8 %yy 39 %ab = xor i8 %a, %b 40 %not_ab = xor i8 %ab, -1 41 ret i8 %not_ab 42} 43 44define i8 @xor_fail(i8 %a, i1 %c, i8 %x, i8 %y) { 45; CHECK-LABEL: @xor_fail( 46; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 47; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[Y:%.*]] 48; CHECK-NEXT: [[AB:%.*]] = xor i8 [[A:%.*]], [[B]] 49; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[AB]], -1 50; CHECK-NEXT: ret i8 [[NOT_AB]] 51; 52 %nx = xor i8 %x, -1 53 %b = select i1 %c, i8 %nx, i8 %y 54 %ab = xor i8 %a, %b 55 %not_ab = xor i8 %ab, -1 56 ret i8 %not_ab 57} 58 59define i8 @add_1(i8 %a, i1 %c, i8 %x, i8 %y) { 60; CHECK-LABEL: @add_1( 61; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124 62; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]] 63; CHECK-NEXT: [[NOT_BA:%.*]] = sub i8 [[TMP2]], [[A:%.*]] 64; CHECK-NEXT: ret i8 [[NOT_BA]] 65; 66 %nx = xor i8 %x, -1 67 %yy = xor i8 %y, 123 68 %b = select i1 %c, i8 %nx, i8 %yy 69 %ba = add i8 %b, %a 70 %not_ba = xor i8 %ba, -1 71 ret i8 %not_ba 72} 73 74define i8 @add_2(i8 %a, i1 %c, i8 %x, i8 %y) { 75; CHECK-LABEL: @add_2( 76; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124 77; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]] 78; CHECK-NEXT: [[NOT_AB:%.*]] = sub i8 [[TMP2]], [[A:%.*]] 79; CHECK-NEXT: ret i8 [[NOT_AB]] 80; 81 %nx = xor i8 %x, -1 82 %yy = xor i8 %y, 123 83 %b = select i1 %c, i8 %nx, i8 %yy 84 %ab = add i8 %a, %b 85 %not_ab = xor i8 %ab, -1 86 ret i8 %not_ab 87} 88 89define i8 @add_fail(i8 %a, i1 %c, i8 %x, i8 %y) { 90; CHECK-LABEL: @add_fail( 91; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], [[A:%.*]] 92; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123 93; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]] 94; CHECK-NEXT: [[AB:%.*]] = add i8 [[A]], [[B]] 95; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[AB]], -1 96; CHECK-NEXT: ret i8 [[NOT_AB]] 97; 98 %nx = xor i8 %x, %a 99 %yy = xor i8 %y, 123 100 %b = select i1 %c, i8 %nx, i8 %yy 101 %ab = add i8 %a, %b 102 %not_ab = xor i8 %ab, -1 103 ret i8 %not_ab 104} 105 106define i8 @sub_1(i8 %a, i1 %c, i8 %x, i8 %y) { 107; CHECK-LABEL: @sub_1( 108; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124 109; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]] 110; CHECK-NEXT: [[NOT_BA:%.*]] = add i8 [[TMP2]], [[A:%.*]] 111; CHECK-NEXT: ret i8 [[NOT_BA]] 112; 113 %nx = xor i8 %x, -1 114 %yy = xor i8 %y, 123 115 %b = select i1 %c, i8 %nx, i8 %yy 116 %ba = sub i8 %b, %a 117 %not_ba = xor i8 %ba, -1 118 ret i8 %not_ba 119} 120 121define i8 @sub_2(i8 %a, i1 %c, i8 %x, i8 %y) { 122; CHECK-LABEL: @sub_2( 123; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124 124; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]] 125; CHECK-NEXT: [[TMP3:%.*]] = add i8 [[TMP2]], [[A:%.*]] 126; CHECK-NEXT: [[NOT_AB:%.*]] = sub i8 -2, [[TMP3]] 127; CHECK-NEXT: ret i8 [[NOT_AB]] 128; 129 %nx = xor i8 %x, -1 130 %yy = xor i8 %y, 123 131 %b = select i1 %c, i8 %nx, i8 %yy 132 %ab = sub i8 %a, %b 133 %not_ab = xor i8 %ab, -1 134 ret i8 %not_ab 135} 136 137; Same as above but with a type larger than i64 to make sure we create -2 138; correctly. 139define i128 @sub_3(i128 %a, i1 %c, i128 %x, i128 %y) { 140; CHECK-LABEL: @sub_3( 141; CHECK-NEXT: [[TMP1:%.*]] = xor i128 [[Y:%.*]], -124 142; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i128 [[X:%.*]], i128 [[TMP1]] 143; CHECK-NEXT: [[TMP3:%.*]] = add i128 [[TMP2]], [[A:%.*]] 144; CHECK-NEXT: [[NOT_AB:%.*]] = sub i128 -2, [[TMP3]] 145; CHECK-NEXT: ret i128 [[NOT_AB]] 146; 147 %nx = xor i128 %x, -1 148 %yy = xor i128 %y, 123 149 %b = select i1 %c, i128 %nx, i128 %yy 150 %ab = sub i128 %a, %b 151 %not_ab = xor i128 %ab, -1 152 ret i128 %not_ab 153} 154 155define i8 @sub_fail(i8 %a, i1 %c, i8 %x, i8 %y) { 156; CHECK-LABEL: @sub_fail( 157; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 158; CHECK-NEXT: call void @use.i8(i8 [[NX]]) 159; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124 160; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X]], i8 [[TMP1]] 161; CHECK-NEXT: [[NOT_BA:%.*]] = add i8 [[TMP2]], [[A:%.*]] 162; CHECK-NEXT: ret i8 [[NOT_BA]] 163; 164 %nx = xor i8 %x, -1 165 %yy = xor i8 %y, 123 166 call void @use.i8(i8 %nx) 167 %b = select i1 %c, i8 %nx, i8 %yy 168 %ba = sub i8 %b, %a 169 %not_ba = xor i8 %ba, -1 170 ret i8 %not_ba 171} 172 173define i8 @ashr_1(i8 %a, i1 %c, i8 %x, i8 %y) { 174; CHECK-LABEL: @ashr_1( 175; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124 176; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]] 177; CHECK-NEXT: [[NOT_BA:%.*]] = ashr i8 [[TMP2]], [[A:%.*]] 178; CHECK-NEXT: ret i8 [[NOT_BA]] 179; 180 %nx = xor i8 %x, -1 181 %yy = xor i8 %y, 123 182 %b = select i1 %c, i8 %nx, i8 %yy 183 %ba = ashr i8 %b, %a 184 %not_ba = xor i8 %ba, -1 185 ret i8 %not_ba 186} 187 188define i8 @ashr_2_fail(i8 %a, i1 %c, i8 %x, i8 %y) { 189; CHECK-LABEL: @ashr_2_fail( 190; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 191; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123 192; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]] 193; CHECK-NEXT: [[AB:%.*]] = ashr i8 [[A:%.*]], [[B]] 194; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[AB]], -1 195; CHECK-NEXT: ret i8 [[NOT_AB]] 196; 197 %nx = xor i8 %x, -1 198 %yy = xor i8 %y, 123 199 %b = select i1 %c, i8 %nx, i8 %yy 200 %ab = ashr i8 %a, %b 201 %not_ab = xor i8 %ab, -1 202 ret i8 %not_ab 203} 204 205define i8 @select_1(i1 %cc, i8 %na, i8 %aa, i1 %c, i8 %x, i8 %y) { 206; CHECK-LABEL: @select_1( 207; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[NA:%.*]], [[AA:%.*]] 208; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[TMP1]], -46 209; CHECK-NEXT: [[TMP3:%.*]] = xor i8 [[Y:%.*]], -124 210; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP3]] 211; CHECK-NEXT: [[NOT_AB:%.*]] = select i1 [[CC:%.*]], i8 [[TMP2]], i8 [[TMP4]] 212; CHECK-NEXT: ret i8 [[NOT_AB]] 213; 214 %nx = xor i8 %x, -1 215 %yy = xor i8 %y, 123 216 %b = select i1 %c, i8 %nx, i8 %yy 217 %nna = xor i8 %na, 45 218 %a = xor i8 %aa, %nna 219 %ab = select i1 %cc, i8 %a, i8 %b 220 %not_ab = xor i8 %ab, -1 221 ret i8 %not_ab 222} 223 224define i8 @select_2(i1 %cc, i8 %na, i1 %c, i8 %x, i8 %y) { 225; CHECK-LABEL: @select_2( 226; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124 227; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]] 228; CHECK-NEXT: [[TMP3:%.*]] = xor i8 [[NA:%.*]], -46 229; CHECK-NEXT: [[NOT_BA:%.*]] = select i1 [[CC:%.*]], i8 [[TMP2]], i8 [[TMP3]] 230; CHECK-NEXT: ret i8 [[NOT_BA]] 231; 232 %nx = xor i8 %x, -1 233 %yy = xor i8 %y, 123 234 %b = select i1 %c, i8 %nx, i8 %yy 235 %a = xor i8 %na, 45 236 %ba = select i1 %cc, i8 %b, i8 %a 237 %not_ba = xor i8 %ba, -1 238 ret i8 %not_ba 239} 240 241define i1 @select_logic_or_fail(i1 %cc, i1 %c, i1 %x, i8 %y) { 242; CHECK-LABEL: @select_logic_or_fail( 243; CHECK-NEXT: [[NX:%.*]] = xor i1 [[X:%.*]], true 244; CHECK-NEXT: [[YY:%.*]] = icmp eq i8 [[Y:%.*]], 123 245; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i1 [[NX]], i1 [[YY]] 246; CHECK-NEXT: [[AB:%.*]] = select i1 [[CC:%.*]], i1 [[B]], i1 false 247; CHECK-NEXT: [[NOT_AB:%.*]] = xor i1 [[AB]], true 248; CHECK-NEXT: ret i1 [[NOT_AB]] 249; 250 %nx = xor i1 %x, -1 251 %yy = icmp eq i8 %y, 123 252 %b = select i1 %c, i1 %nx, i1 %yy 253 %ab = select i1 %cc, i1 %b, i1 false 254 %not_ab = xor i1 %ab, -1 255 ret i1 %not_ab 256} 257 258define i1 @select_logic_and_fail(i1 %cc, i1 %c, i1 %x, i8 %y) { 259; CHECK-LABEL: @select_logic_and_fail( 260; CHECK-NEXT: [[NX:%.*]] = xor i1 [[X:%.*]], true 261; CHECK-NEXT: [[YY:%.*]] = icmp eq i8 [[Y:%.*]], 123 262; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i1 [[NX]], i1 [[YY]] 263; CHECK-NEXT: [[AB:%.*]] = select i1 [[CC:%.*]], i1 true, i1 [[B]] 264; CHECK-NEXT: [[NOT_AB:%.*]] = xor i1 [[AB]], true 265; CHECK-NEXT: ret i1 [[NOT_AB]] 266; 267 %nx = xor i1 %x, -1 268 %yy = icmp eq i8 %y, 123 269 %b = select i1 %c, i1 %nx, i1 %yy 270 %ab = select i1 %cc, i1 true, i1 %b 271 %not_ab = xor i1 %ab, -1 272 ret i1 %not_ab 273} 274 275define i8 @smin_1(i8 %aa, i8 %na, i1 %c, i8 %x, i8 %y) { 276; CHECK-LABEL: @smin_1( 277; CHECK-NEXT: [[TMP1:%.*]] = sub i8 [[NA:%.*]], [[AA:%.*]] 278; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[Y:%.*]], -124 279; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP2]] 280; CHECK-NEXT: [[NOT_AB:%.*]] = call i8 @llvm.smax.i8(i8 [[TMP1]], i8 [[TMP3]]) 281; CHECK-NEXT: ret i8 [[NOT_AB]] 282; 283 %nx = xor i8 %x, -1 284 %yy = xor i8 %y, 123 285 %b = select i1 %c, i8 %nx, i8 %yy 286 %nna = xor i8 %na, -1 287 %a = add i8 %aa, %nna 288 %ab = call i8 @llvm.smin.i8(i8 %a, i8 %b) 289 %not_ab = xor i8 %ab, -1 290 ret i8 %not_ab 291} 292 293define i8 @smin_1_fail(i8 %a, i1 %c, i8 %x, i8 %y) { 294; CHECK-LABEL: @smin_1_fail( 295; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 296; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123 297; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]] 298; CHECK-NEXT: [[AB:%.*]] = call i8 @llvm.smin.i8(i8 [[A:%.*]], i8 [[B]]) 299; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[AB]], -1 300; CHECK-NEXT: ret i8 [[NOT_AB]] 301; 302 %nx = xor i8 %x, -1 303 %yy = xor i8 %y, 123 304 %b = select i1 %c, i8 %nx, i8 %yy 305 %ab = call i8 @llvm.smin.i8(i8 %a, i8 %b) 306 %not_ab = xor i8 %ab, -1 307 ret i8 %not_ab 308} 309 310define i8 @umin_1_fail(i1 %c, i8 %x, i8 %y) { 311; CHECK-LABEL: @umin_1_fail( 312; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 313; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[Y:%.*]] 314; CHECK-NEXT: [[BA:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 85) 315; CHECK-NEXT: [[NOT_BA:%.*]] = xor i8 [[BA]], -1 316; CHECK-NEXT: ret i8 [[NOT_BA]] 317; 318 %nx = xor i8 %x, -1 319 %b = select i1 %c, i8 %nx, i8 %y 320 %ba = call i8 @llvm.umin.i8(i8 %b, i8 85) 321 %not_ba = xor i8 %ba, -1 322 ret i8 %not_ba 323} 324 325define i8 @smax_1(i8 %aa, i8 %na, i1 %c, i8 %x, i8 %y) { 326; CHECK-LABEL: @smax_1( 327; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[NA:%.*]], [[AA:%.*]] 328; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[Y:%.*]], -124 329; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP2]] 330; CHECK-NEXT: [[NOT_AB:%.*]] = call i8 @llvm.smin.i8(i8 [[TMP1]], i8 [[TMP3]]) 331; CHECK-NEXT: ret i8 [[NOT_AB]] 332; 333 %nx = xor i8 %x, -1 334 %yy = xor i8 %y, 123 335 %b = select i1 %c, i8 %nx, i8 %yy 336 %nna = xor i8 %na, -1 337 %a = sub i8 %nna, %aa 338 %ab = call i8 @llvm.smax.i8(i8 %a, i8 %b) 339 %not_ab = xor i8 %ab, -1 340 ret i8 %not_ab 341} 342 343define i8 @smax_1_fail(i8 %aa, i8 %na, i1 %c, i8 %x, i8 %y) { 344; CHECK-LABEL: @smax_1_fail( 345; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 346; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123 347; CHECK-NEXT: call void @use.i8(i8 [[YY]]) 348; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]] 349; CHECK-NEXT: [[NNA:%.*]] = xor i8 [[NA:%.*]], -1 350; CHECK-NEXT: [[A:%.*]] = sub i8 [[NNA]], [[AA:%.*]] 351; CHECK-NEXT: [[AB:%.*]] = call i8 @llvm.smax.i8(i8 [[A]], i8 [[B]]) 352; CHECK-NEXT: [[NOT_AB:%.*]] = xor i8 [[AB]], -1 353; CHECK-NEXT: ret i8 [[NOT_AB]] 354; 355 %nx = xor i8 %x, -1 356 %yy = xor i8 %y, 123 357 call void @use.i8(i8 %yy) 358 %b = select i1 %c, i8 %nx, i8 %yy 359 %nna = xor i8 %na, -1 360 %a = sub i8 %nna, %aa 361 %ab = call i8 @llvm.smax.i8(i8 %a, i8 %b) 362 %not_ab = xor i8 %ab, -1 363 ret i8 %not_ab 364} 365 366define i8 @umax_1(i8 %na, i1 %c, i8 %x, i8 %y) { 367; CHECK-LABEL: @umax_1( 368; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[Y:%.*]], -124 369; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C:%.*]], i8 [[X:%.*]], i8 [[TMP1]] 370; CHECK-NEXT: [[NOT_BA:%.*]] = call i8 @llvm.umin.i8(i8 [[TMP2]], i8 -86) 371; CHECK-NEXT: ret i8 [[NOT_BA]] 372; 373 %nx = xor i8 %x, -1 374 %yy = xor i8 %y, 123 375 %b = select i1 %c, i8 %nx, i8 %yy 376 %ba = call i8 @llvm.umax.i8(i8 %b, i8 85) 377 %not_ba = xor i8 %ba, -1 378 ret i8 %not_ba 379} 380 381define i8 @umax_1_fail(i8 %na, i1 %c, i8 %x, i8 %y) { 382; CHECK-LABEL: @umax_1_fail( 383; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1 384; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 123 385; CHECK-NEXT: [[B:%.*]] = select i1 [[C:%.*]], i8 [[NX]], i8 [[YY]] 386; CHECK-NEXT: call void @use.i8(i8 [[B]]) 387; CHECK-NEXT: [[BA:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 85) 388; CHECK-NEXT: [[NOT_BA:%.*]] = xor i8 [[BA]], -1 389; CHECK-NEXT: ret i8 [[NOT_BA]] 390; 391 %nx = xor i8 %x, -1 392 %yy = xor i8 %y, 123 393 %b = select i1 %c, i8 %nx, i8 %yy 394 call void @use.i8(i8 %b) 395 %ba = call i8 @llvm.umax.i8(i8 %b, i8 85) 396 %not_ba = xor i8 %ba, -1 397 ret i8 %not_ba 398} 399 400define i8 @sub_both_freely_invertable_always(i8 %x, i8 %y) { 401; CHECK-LABEL: @sub_both_freely_invertable_always( 402; CHECK-NEXT: [[XX:%.*]] = xor i8 [[X:%.*]], 123 403; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 45 404; CHECK-NEXT: [[R:%.*]] = sub i8 [[XX]], [[YY]] 405; CHECK-NEXT: ret i8 [[R]] 406; 407 %xx = xor i8 %x, 123 408 %yy = xor i8 %y, 45 409 %r = sub i8 %xx, %yy 410 ret i8 %r 411} 412 413define i8 @add_both_freely_invertable_always(i8 %x, i8 %y) { 414; CHECK-LABEL: @add_both_freely_invertable_always( 415; CHECK-NEXT: [[XX:%.*]] = xor i8 [[X:%.*]], 123 416; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 45 417; CHECK-NEXT: [[R:%.*]] = add i8 [[XX]], [[YY]] 418; CHECK-NEXT: ret i8 [[R]] 419; 420 %xx = xor i8 %x, 123 421 %yy = xor i8 %y, 45 422 %r = add i8 %xx, %yy 423 ret i8 %r 424} 425 426define i8 @xor_both_freely_invertable_always(i8 %x, i8 %y) { 427; CHECK-LABEL: @xor_both_freely_invertable_always( 428; CHECK-NEXT: [[XX:%.*]] = add i8 [[X:%.*]], 123 429; CHECK-NEXT: [[YY:%.*]] = add i8 [[Y:%.*]], 45 430; CHECK-NEXT: [[R:%.*]] = xor i8 [[XX]], [[YY]] 431; CHECK-NEXT: ret i8 [[R]] 432; 433 %xx = add i8 %x, 123 434 %yy = add i8 %y, 45 435 %r = xor i8 %xx, %yy 436 ret i8 %r 437} 438 439define i8 @ashr_both_freely_invertable_always(i8 %x, i8 %y) { 440; CHECK-LABEL: @ashr_both_freely_invertable_always( 441; CHECK-NEXT: [[XX:%.*]] = xor i8 [[X:%.*]], 123 442; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 45 443; CHECK-NEXT: [[R:%.*]] = ashr i8 [[XX]], [[YY]] 444; CHECK-NEXT: ret i8 [[R]] 445; 446 %xx = xor i8 %x, 123 447 %yy = xor i8 %y, 45 448 %r = ashr i8 %xx, %yy 449 ret i8 %r 450} 451 452define i8 @select_both_freely_invertable_always(i1 %cc, i8 %x, i8 %y) { 453; CHECK-LABEL: @select_both_freely_invertable_always( 454; CHECK-NEXT: [[XX:%.*]] = xor i8 [[X:%.*]], 123 455; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 45 456; CHECK-NEXT: [[R:%.*]] = select i1 [[CC:%.*]], i8 [[XX]], i8 [[YY]] 457; CHECK-NEXT: ret i8 [[R]] 458; 459 %xx = xor i8 %x, 123 460 %yy = xor i8 %y, 45 461 %r = select i1 %cc, i8 %xx, i8 %yy 462 ret i8 %r 463} 464 465define i8 @umin_both_freely_invertable_always(i8 %x, i8 %y) { 466; CHECK-LABEL: @umin_both_freely_invertable_always( 467; CHECK-NEXT: [[XX:%.*]] = xor i8 [[X:%.*]], 123 468; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 45 469; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[XX]], i8 [[YY]]) 470; CHECK-NEXT: ret i8 [[R]] 471; 472 %xx = xor i8 %x, 123 473 %yy = xor i8 %y, 45 474 %r = call i8 @llvm.umin.i8(i8 %xx, i8 %yy) 475 ret i8 %r 476} 477 478define i8 @umax_both_freely_invertable_always(i8 %x, i8 %y) { 479; CHECK-LABEL: @umax_both_freely_invertable_always( 480; CHECK-NEXT: [[XX:%.*]] = xor i8 [[X:%.*]], 123 481; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 45 482; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umax.i8(i8 [[XX]], i8 [[YY]]) 483; CHECK-NEXT: ret i8 [[R]] 484; 485 %xx = xor i8 %x, 123 486 %yy = xor i8 %y, 45 487 %r = call i8 @llvm.umax.i8(i8 %xx, i8 %yy) 488 ret i8 %r 489} 490 491define i8 @smin_both_freely_invertable_always(i8 %x, i8 %y) { 492; CHECK-LABEL: @smin_both_freely_invertable_always( 493; CHECK-NEXT: [[XX:%.*]] = xor i8 [[X:%.*]], 123 494; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 45 495; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smin.i8(i8 [[XX]], i8 [[YY]]) 496; CHECK-NEXT: ret i8 [[R]] 497; 498 %xx = xor i8 %x, 123 499 %yy = xor i8 %y, 45 500 %r = call i8 @llvm.smin.i8(i8 %xx, i8 %yy) 501 ret i8 %r 502} 503 504define i8 @smax_both_freely_invertable_always(i8 %x, i8 %y) { 505; CHECK-LABEL: @smax_both_freely_invertable_always( 506; CHECK-NEXT: [[XX:%.*]] = xor i8 [[X:%.*]], 123 507; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 45 508; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.smax.i8(i8 [[XX]], i8 [[YY]]) 509; CHECK-NEXT: ret i8 [[R]] 510; 511 %xx = xor i8 %x, 123 512 %yy = xor i8 %y, 45 513 %r = call i8 @llvm.smax.i8(i8 %xx, i8 %yy) 514 ret i8 %r 515} 516 517define i8 @lshr_nneg(i8 %x, i8 %y) { 518; CHECK-LABEL: @lshr_nneg( 519; CHECK-NEXT: [[NEG:%.*]] = icmp slt i8 [[X:%.*]], 0 520; CHECK-NEXT: call void @llvm.assume(i1 [[NEG]]) 521; CHECK-NEXT: [[SHR_NOT:%.*]] = ashr i8 [[X]], [[Y:%.*]] 522; CHECK-NEXT: ret i8 [[SHR_NOT]] 523; 524 %neg = icmp slt i8 %x, 0 525 call void @llvm.assume(i1 %neg) 526 %x.not = xor i8 %x, -1 527 %shr = lshr i8 %x.not, %y 528 %shr.not = xor i8 %shr, -1 529 ret i8 %shr.not 530} 531 532define i8 @lshr_not_nneg(i8 %x, i8 %y) { 533; CHECK-LABEL: @lshr_not_nneg( 534; CHECK-NEXT: [[X_NOT:%.*]] = xor i8 [[X:%.*]], -1 535; CHECK-NEXT: [[SHR:%.*]] = lshr i8 [[X_NOT]], [[Y:%.*]] 536; CHECK-NEXT: [[SHR_NOT:%.*]] = xor i8 [[SHR]], -1 537; CHECK-NEXT: ret i8 [[SHR_NOT]] 538; 539 %x.not = xor i8 %x, -1 540 %shr = lshr i8 %x.not, %y 541 %shr.not = xor i8 %shr, -1 542 ret i8 %shr.not 543} 544 545define i8 @lshr_not_nneg2(i8 %x) { 546; CHECK-LABEL: @lshr_not_nneg2( 547; CHECK-NEXT: [[SHR:%.*]] = lshr i8 [[X:%.*]], 1 548; CHECK-NEXT: [[SHR_NOT:%.*]] = or disjoint i8 [[SHR]], -128 549; CHECK-NEXT: ret i8 [[SHR_NOT]] 550; 551 %x.not = xor i8 %x, -1 552 %shr = lshr i8 %x.not, 1 553 %shr.not = xor i8 %shr, -1 554 ret i8 %shr.not 555} 556 557define i1 @test_inv_free(i1 %c1, i1 %c2, i1 %c3, i1 %c4) { 558; CHECK-LABEL: @test_inv_free( 559; CHECK-NEXT: entry: 560; CHECK-NEXT: br i1 [[C1:%.*]], label [[B1:%.*]], label [[B2:%.*]] 561; CHECK: b1: 562; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[B3:%.*]] 563; CHECK: b2: 564; CHECK-NEXT: br label [[EXIT]] 565; CHECK: b3: 566; CHECK-NEXT: br label [[EXIT]] 567; CHECK: exit: 568; CHECK-NEXT: [[VAL_NOT:%.*]] = phi i1 [ false, [[B1]] ], [ true, [[B2]] ], [ [[C3:%.*]], [[B3]] ] 569; CHECK-NEXT: [[COND_NOT:%.*]] = and i1 [[VAL_NOT]], [[C4:%.*]] 570; CHECK-NEXT: br i1 [[COND_NOT]], label [[B5:%.*]], label [[B4:%.*]] 571; CHECK: b4: 572; CHECK-NEXT: ret i1 true 573; CHECK: b5: 574; CHECK-NEXT: ret i1 false 575; 576entry: 577 br i1 %c1, label %b1, label %b2 578b1: 579 br i1 %c2, label %exit, label %b3 580b2: 581 br label %exit 582b3: 583 %invc3 = xor i1 %c3, true 584 br label %exit 585exit: 586 %val = phi i1 [ true, %b1 ], [ false, %b2 ], [ %invc3, %b3 ] 587 %inv = xor i1 %c4, true 588 %cond = or i1 %val, %inv 589 br i1 %cond, label %b4, label %b5 590b4: 591 ret i1 true 592b5: 593 ret i1 false 594} 595 596define i32 @test_inv_free_i32(i1 %c1, i1 %c2, i32 %c3, i32 %c4) { 597; CHECK-LABEL: @test_inv_free_i32( 598; CHECK-NEXT: entry: 599; CHECK-NEXT: br i1 [[C1:%.*]], label [[B1:%.*]], label [[B2:%.*]] 600; CHECK: b1: 601; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[B3:%.*]] 602; CHECK: b2: 603; CHECK-NEXT: br label [[EXIT]] 604; CHECK: b3: 605; CHECK-NEXT: br label [[EXIT]] 606; CHECK: exit: 607; CHECK-NEXT: [[TMP0:%.*]] = phi i32 [ 0, [[B1]] ], [ -1, [[B2]] ], [ [[C3:%.*]], [[B3]] ] 608; CHECK-NEXT: [[COND:%.*]] = xor i32 [[C4:%.*]], [[TMP0]] 609; CHECK-NEXT: ret i32 [[COND]] 610; 611entry: 612 br i1 %c1, label %b1, label %b2 613b1: 614 br i1 %c2, label %exit, label %b3 615b2: 616 br label %exit 617b3: 618 %invc3 = xor i32 %c3, -1 619 br label %exit 620exit: 621 %val = phi i32 [ -1, %b1 ], [ 0, %b2 ], [ %invc3, %b3 ] 622 %inv = xor i32 %c4, -1 623 %cond = xor i32 %val, %inv 624 ret i32 %cond 625} 626 627; Negative tests 628 629define i1 @test_inv_free_multiuse(i1 %c1, i1 %c2, i1 %c3, i1 %c4) { 630; CHECK-LABEL: @test_inv_free_multiuse( 631; CHECK-NEXT: entry: 632; CHECK-NEXT: br i1 [[C1:%.*]], label [[B1:%.*]], label [[B2:%.*]] 633; CHECK: b1: 634; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[B3:%.*]] 635; CHECK: b2: 636; CHECK-NEXT: br label [[EXIT]] 637; CHECK: b3: 638; CHECK-NEXT: [[INVC3:%.*]] = xor i1 [[C3:%.*]], true 639; CHECK-NEXT: br label [[EXIT]] 640; CHECK: exit: 641; CHECK-NEXT: [[VAL:%.*]] = phi i1 [ true, [[B1]] ], [ false, [[B2]] ], [ [[INVC3]], [[B3]] ] 642; CHECK-NEXT: call void @use.i1(i1 [[VAL]]) 643; CHECK-NEXT: [[INV:%.*]] = xor i1 [[C4:%.*]], true 644; CHECK-NEXT: [[COND:%.*]] = or i1 [[VAL]], [[INV]] 645; CHECK-NEXT: br i1 [[COND]], label [[B4:%.*]], label [[B5:%.*]] 646; CHECK: b4: 647; CHECK-NEXT: ret i1 true 648; CHECK: b5: 649; CHECK-NEXT: ret i1 false 650; 651entry: 652 br i1 %c1, label %b1, label %b2 653b1: 654 br i1 %c2, label %exit, label %b3 655b2: 656 br label %exit 657b3: 658 %invc3 = xor i1 %c3, true 659 br label %exit 660exit: 661 %val = phi i1 [ true, %b1 ], [ false, %b2 ], [ %invc3, %b3 ] 662 call void @use.i1(i1 %val) 663 %inv = xor i1 %c4, true 664 %cond = or i1 %val, %inv 665 br i1 %cond, label %b4, label %b5 666b4: 667 ret i1 true 668b5: 669 ret i1 false 670} 671 672define i32 @test_inv_free_i32_newinst(i1 %c1, i1 %c2, i32 %c3, i32 %c4) { 673; CHECK-LABEL: @test_inv_free_i32_newinst( 674; CHECK-NEXT: entry: 675; CHECK-NEXT: br i1 [[C1:%.*]], label [[B1:%.*]], label [[B2:%.*]] 676; CHECK: b1: 677; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[B3:%.*]] 678; CHECK: b2: 679; CHECK-NEXT: br label [[EXIT]] 680; CHECK: b3: 681; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 -8, [[C3:%.*]] 682; CHECK-NEXT: br label [[EXIT]] 683; CHECK: exit: 684; CHECK-NEXT: [[VAL:%.*]] = phi i32 [ -1, [[B1]] ], [ 0, [[B2]] ], [ [[ASHR]], [[B3]] ] 685; CHECK-NEXT: [[TMP0:%.*]] = xor i32 [[C4:%.*]], [[VAL]] 686; CHECK-NEXT: [[COND:%.*]] = xor i32 [[TMP0]], -1 687; CHECK-NEXT: ret i32 [[COND]] 688; 689entry: 690 br i1 %c1, label %b1, label %b2 691b1: 692 br i1 %c2, label %exit, label %b3 693b2: 694 br label %exit 695b3: 696 %ashr = ashr i32 -8, %c3 697 br label %exit 698exit: 699 %val = phi i32 [ -1, %b1 ], [ 0, %b2 ], [ %ashr, %b3 ] 700 %inv = xor i32 %c4, -1 701 %cond = xor i32 %val, %inv 702 ret i32 %cond 703} 704 705define i1 @test_inv_free_loop(i1 %c1, i1 %c2, i1 %c3, i1 %c4) { 706; CHECK-LABEL: @test_inv_free_loop( 707; CHECK-NEXT: entry: 708; CHECK-NEXT: br i1 [[C1:%.*]], label [[B1:%.*]], label [[B2:%.*]] 709; CHECK: b1: 710; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[B3:%.*]] 711; CHECK: b2: 712; CHECK-NEXT: br label [[EXIT]] 713; CHECK: b3: 714; CHECK-NEXT: [[INVC3:%.*]] = xor i1 [[C3:%.*]], true 715; CHECK-NEXT: br label [[EXIT]] 716; CHECK: exit: 717; CHECK-NEXT: [[VAL:%.*]] = phi i1 [ true, [[B1]] ], [ false, [[B2]] ], [ [[INVC3]], [[B3]] ], [ [[NOT:%.*]], [[EXIT]] ] 718; CHECK-NEXT: [[INV:%.*]] = xor i1 [[C4:%.*]], true 719; CHECK-NEXT: [[COND:%.*]] = or i1 [[VAL]], [[INV]] 720; CHECK-NEXT: [[NOT]] = xor i1 [[VAL]], true 721; CHECK-NEXT: br i1 [[COND]], label [[EXIT]], label [[B4:%.*]] 722; CHECK: b4: 723; CHECK-NEXT: ret i1 true 724; 725entry: 726 br i1 %c1, label %b1, label %b2 727b1: 728 br i1 %c2, label %exit, label %b3 729b2: 730 br label %exit 731b3: 732 %invc3 = xor i1 %c3, true 733 br label %exit 734exit: 735 %val = phi i1 [ true, %b1 ], [ false, %b2 ], [ %invc3, %b3 ], [ %not, %exit ] 736 %inv = xor i1 %c4, true 737 %cond = or i1 %val, %inv 738 %not = xor i1 %val, true 739 br i1 %cond, label %exit, label %b4 740b4: 741 ret i1 true 742} 743