1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" 5 6declare i32 @abs(i32) 7declare i64 @labs(i64) 8declare i64 @llabs(i64) 9 10; Test that the abs library call simplifier works correctly. 11; abs(x) -> x <s 0 ? -x : x. 12 13define i32 @test_abs(i32 %x) { 14; CHECK-LABEL: @test_abs( 15; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.abs.i32(i32 [[X:%.*]], i1 true) 16; CHECK-NEXT: ret i32 [[RET]] 17; 18 %ret = call i32 @abs(i32 %x) 19 ret i32 %ret 20} 21 22define i64 @test_labs(i64 %x) { 23; CHECK-LABEL: @test_labs( 24; CHECK-NEXT: [[RET:%.*]] = call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 true) 25; CHECK-NEXT: ret i64 [[RET]] 26; 27 %ret = call i64 @labs(i64 %x) 28 ret i64 %ret 29} 30 31define i64 @test_llabs(i64 %x) { 32; CHECK-LABEL: @test_llabs( 33; CHECK-NEXT: [[RET:%.*]] = call i64 @llvm.abs.i64(i64 [[X:%.*]], i1 true) 34; CHECK-NEXT: ret i64 [[RET]] 35; 36 %ret = call i64 @llabs(i64 %x) 37 ret i64 %ret 38} 39 40; We have a canonical form of abs to make CSE easier. 41 42define i8 @abs_canonical_1(i8 %x) { 43; CHECK-LABEL: @abs_canonical_1( 44; CHECK-NEXT: [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) 45; CHECK-NEXT: ret i8 [[ABS]] 46; 47 %cmp = icmp sgt i8 %x, 0 48 %neg = sub i8 0, %x 49 %abs = select i1 %cmp, i8 %x, i8 %neg 50 ret i8 %abs 51} 52 53; Vectors should work too. 54 55define <2 x i8> @abs_canonical_2(<2 x i8> %x) { 56; CHECK-LABEL: @abs_canonical_2( 57; CHECK-NEXT: [[ABS:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false) 58; CHECK-NEXT: ret <2 x i8> [[ABS]] 59; 60 %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 -1> 61 %neg = sub <2 x i8> zeroinitializer, %x 62 %abs = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> %neg 63 ret <2 x i8> %abs 64} 65 66; Even if a constant has poison elements. 67 68define <2 x i8> @abs_canonical_2_vec_poison_elts(<2 x i8> %x) { 69; CHECK-LABEL: @abs_canonical_2_vec_poison_elts( 70; CHECK-NEXT: [[ABS:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false) 71; CHECK-NEXT: ret <2 x i8> [[ABS]] 72; 73 %cmp = icmp sgt <2 x i8> %x, <i8 poison, i8 -1> 74 %neg = sub <2 x i8> zeroinitializer, %x 75 %abs = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> %neg 76 ret <2 x i8> %abs 77} 78 79; NSW should not change. 80 81define i8 @abs_canonical_3(i8 %x) { 82; CHECK-LABEL: @abs_canonical_3( 83; CHECK-NEXT: [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true) 84; CHECK-NEXT: ret i8 [[ABS]] 85; 86 %cmp = icmp slt i8 %x, 0 87 %neg = sub nsw i8 0, %x 88 %abs = select i1 %cmp, i8 %neg, i8 %x 89 ret i8 %abs 90} 91 92define i8 @abs_canonical_4(i8 %x) { 93; CHECK-LABEL: @abs_canonical_4( 94; CHECK-NEXT: [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) 95; CHECK-NEXT: ret i8 [[ABS]] 96; 97 %cmp = icmp slt i8 %x, 1 98 %neg = sub i8 0, %x 99 %abs = select i1 %cmp, i8 %neg, i8 %x 100 ret i8 %abs 101} 102 103define i32 @abs_canonical_5(i8 %x) { 104; CHECK-LABEL: @abs_canonical_5( 105; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) 106; CHECK-NEXT: [[ABS:%.*]] = zext i8 [[TMP1]] to i32 107; CHECK-NEXT: ret i32 [[ABS]] 108; 109 %cmp = icmp sgt i8 %x, 0 110 %conv = sext i8 %x to i32 111 %neg = sub i32 0, %conv 112 %abs = select i1 %cmp, i32 %conv, i32 %neg 113 ret i32 %abs 114} 115 116define i32 @abs_canonical_6(i32 %a, i32 %b) { 117; CHECK-LABEL: @abs_canonical_6( 118; CHECK-NEXT: [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 119; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false) 120; CHECK-NEXT: ret i32 [[ABS]] 121; 122 %t1 = sub i32 %a, %b 123 %cmp = icmp sgt i32 %t1, -1 124 %t2 = sub i32 %b, %a 125 %abs = select i1 %cmp, i32 %t1, i32 %t2 126 ret i32 %abs 127} 128 129define <2 x i8> @abs_canonical_7(<2 x i8> %a, <2 x i8 > %b) { 130; CHECK-LABEL: @abs_canonical_7( 131; CHECK-NEXT: [[T1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]] 132; CHECK-NEXT: [[ABS:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[T1]], i1 false) 133; CHECK-NEXT: ret <2 x i8> [[ABS]] 134; 135 136 %t1 = sub <2 x i8> %a, %b 137 %cmp = icmp sgt <2 x i8> %t1, <i8 -1, i8 -1> 138 %t2 = sub <2 x i8> %b, %a 139 %abs = select <2 x i1> %cmp, <2 x i8> %t1, <2 x i8> %t2 140 ret <2 x i8> %abs 141} 142 143define i32 @abs_canonical_8(i32 %a) { 144; CHECK-LABEL: @abs_canonical_8( 145; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 false) 146; CHECK-NEXT: ret i32 [[ABS]] 147; 148 %t = sub i32 0, %a 149 %cmp = icmp slt i32 %t, 0 150 %abs = select i1 %cmp, i32 %a, i32 %t 151 ret i32 %abs 152} 153 154define i32 @abs_canonical_9(i32 %a, i32 %b) { 155; CHECK-LABEL: @abs_canonical_9( 156; CHECK-NEXT: [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 157; CHECK-NEXT: [[T2:%.*]] = sub i32 [[B]], [[A]] 158; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false) 159; CHECK-NEXT: [[ADD:%.*]] = add i32 [[ABS]], [[T2]] 160; CHECK-NEXT: ret i32 [[ADD]] 161; 162 %t1 = sub i32 %a, %b 163 %cmp = icmp sgt i32 %t1, -1 164 %t2 = sub i32 %b, %a 165 %abs = select i1 %cmp, i32 %t1, i32 %t2 166 %add = add i32 %abs, %t2 ; increase use count for %t2. 167 ret i32 %add 168} 169 170define i32 @abs_canonical_10(i32 %a, i32 %b) { 171; CHECK-LABEL: @abs_canonical_10( 172; CHECK-NEXT: [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 173; CHECK-NEXT: [[ABS:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false) 174; CHECK-NEXT: ret i32 [[ABS]] 175; 176 %t2 = sub i32 %b, %a 177 %t1 = sub i32 %a, %b 178 %cmp = icmp sgt i32 %t1, -1 179 %abs = select i1 %cmp, i32 %t1, i32 %t2 180 ret i32 %abs 181} 182 183; We have a canonical form of nabs to make CSE easier. 184 185define i8 @nabs_canonical_1(i8 %x) { 186; CHECK-LABEL: @nabs_canonical_1( 187; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) 188; CHECK-NEXT: [[ABS:%.*]] = sub i8 0, [[TMP1]] 189; CHECK-NEXT: ret i8 [[ABS]] 190; 191 %cmp = icmp sgt i8 %x, 0 192 %neg = sub i8 0, %x 193 %abs = select i1 %cmp, i8 %neg, i8 %x 194 ret i8 %abs 195} 196 197; Vectors should work too. 198 199define <2 x i8> @nabs_canonical_2(<2 x i8> %x) { 200; CHECK-LABEL: @nabs_canonical_2( 201; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false) 202; CHECK-NEXT: [[ABS:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]] 203; CHECK-NEXT: ret <2 x i8> [[ABS]] 204; 205 %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 -1> 206 %neg = sub <2 x i8> zeroinitializer, %x 207 %abs = select <2 x i1> %cmp, <2 x i8> %neg, <2 x i8> %x 208 ret <2 x i8> %abs 209} 210 211; Even if a constant has poison elements. 212 213define <2 x i8> @nabs_canonical_2_vec_poison_elts(<2 x i8> %x) { 214; CHECK-LABEL: @nabs_canonical_2_vec_poison_elts( 215; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false) 216; CHECK-NEXT: [[ABS:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]] 217; CHECK-NEXT: ret <2 x i8> [[ABS]] 218; 219 %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 poison> 220 %neg = sub <2 x i8> zeroinitializer, %x 221 %abs = select <2 x i1> %cmp, <2 x i8> %neg, <2 x i8> %x 222 ret <2 x i8> %abs 223} 224 225; NSW should not change. 226 227define i8 @nabs_canonical_3(i8 %x) { 228; CHECK-LABEL: @nabs_canonical_3( 229; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) 230; CHECK-NEXT: [[ABS:%.*]] = sub i8 0, [[TMP1]] 231; CHECK-NEXT: ret i8 [[ABS]] 232; 233 %cmp = icmp slt i8 %x, 0 234 %neg = sub nsw i8 0, %x 235 %abs = select i1 %cmp, i8 %x, i8 %neg 236 ret i8 %abs 237} 238 239define i8 @nabs_canonical_4(i8 %x) { 240; CHECK-LABEL: @nabs_canonical_4( 241; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) 242; CHECK-NEXT: [[ABS:%.*]] = sub i8 0, [[TMP1]] 243; CHECK-NEXT: ret i8 [[ABS]] 244; 245 %cmp = icmp slt i8 %x, 1 246 %neg = sub i8 0, %x 247 %abs = select i1 %cmp, i8 %x, i8 %neg 248 ret i8 %abs 249} 250 251define i32 @nabs_canonical_5(i8 %x) { 252; CHECK-LABEL: @nabs_canonical_5( 253; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) 254; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 255; CHECK-NEXT: [[ABS:%.*]] = sub nsw i32 0, [[TMP2]] 256; CHECK-NEXT: ret i32 [[ABS]] 257; 258 %cmp = icmp sgt i8 %x, 0 259 %conv = sext i8 %x to i32 260 %neg = sub i32 0, %conv 261 %abs = select i1 %cmp, i32 %neg, i32 %conv 262 ret i32 %abs 263} 264 265define i32 @nabs_canonical_6(i32 %a, i32 %b) { 266; CHECK-LABEL: @nabs_canonical_6( 267; CHECK-NEXT: [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 268; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false) 269; CHECK-NEXT: [[ABS:%.*]] = sub i32 0, [[TMP1]] 270; CHECK-NEXT: ret i32 [[ABS]] 271; 272 %t1 = sub i32 %a, %b 273 %cmp = icmp sgt i32 %t1, -1 274 %t2 = sub i32 %b, %a 275 %abs = select i1 %cmp, i32 %t2, i32 %t1 276 ret i32 %abs 277} 278 279define <2 x i8> @nabs_canonical_7(<2 x i8> %a, <2 x i8 > %b) { 280; CHECK-LABEL: @nabs_canonical_7( 281; CHECK-NEXT: [[T1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]] 282; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[T1]], i1 false) 283; CHECK-NEXT: [[ABS:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]] 284; CHECK-NEXT: ret <2 x i8> [[ABS]] 285; 286 %t1 = sub <2 x i8> %a, %b 287 %cmp = icmp sgt <2 x i8> %t1, <i8 -1, i8 -1> 288 %t2 = sub <2 x i8> %b, %a 289 %abs = select <2 x i1> %cmp, <2 x i8> %t2, <2 x i8> %t1 290 ret <2 x i8> %abs 291} 292 293define i32 @nabs_canonical_8(i32 %a) { 294; CHECK-LABEL: @nabs_canonical_8( 295; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[A:%.*]], i1 false) 296; CHECK-NEXT: [[ABS:%.*]] = sub i32 0, [[TMP1]] 297; CHECK-NEXT: ret i32 [[ABS]] 298; 299 %t = sub i32 0, %a 300 %cmp = icmp slt i32 %t, 0 301 %abs = select i1 %cmp, i32 %t, i32 %a 302 ret i32 %abs 303} 304 305define i32 @nabs_canonical_9(i32 %a, i32 %b) { 306; CHECK-LABEL: @nabs_canonical_9( 307; CHECK-NEXT: [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 308; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false) 309; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[A]], [[TMP1]] 310; CHECK-NEXT: [[ADD:%.*]] = sub i32 [[B]], [[TMP2]] 311; CHECK-NEXT: ret i32 [[ADD]] 312; 313 %t1 = sub i32 %a, %b 314 %cmp = icmp sgt i32 %t1, -1 315 %t2 = sub i32 %b, %a 316 %abs = select i1 %cmp, i32 %t2, i32 %t1 317 %add = add i32 %t2, %abs ; increase use count for %t2 318 ret i32 %add 319} 320 321define i32 @nabs_canonical_10(i32 %a, i32 %b) { 322; CHECK-LABEL: @nabs_canonical_10( 323; CHECK-NEXT: [[T1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 324; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[T1]], i1 false) 325; CHECK-NEXT: [[ABS:%.*]] = sub i32 0, [[TMP1]] 326; CHECK-NEXT: ret i32 [[ABS]] 327; 328 %t2 = sub i32 %b, %a 329 %t1 = sub i32 %a, %b 330 %cmp = icmp slt i32 %t1, 1 331 %abs = select i1 %cmp, i32 %t1, i32 %t2 332 ret i32 %abs 333} 334 335; The following 5 tests use a shift+add+xor to implement abs(): 336; B = ashr i8 A, 7 -- smear the sign bit. 337; xor (add A, B), B -- add -1 and flip bits if negative 338 339define i8 @shifty_abs_commute0(i8 %x) { 340; CHECK-LABEL: @shifty_abs_commute0( 341; CHECK-NEXT: [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) 342; CHECK-NEXT: ret i8 [[ABS]] 343; 344 %signbit = ashr i8 %x, 7 345 %add = add i8 %signbit, %x 346 %abs = xor i8 %add, %signbit 347 ret i8 %abs 348} 349 350define i8 @shifty_abs_commute0_nsw(i8 %x) { 351; CHECK-LABEL: @shifty_abs_commute0_nsw( 352; CHECK-NEXT: [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true) 353; CHECK-NEXT: ret i8 [[ABS]] 354; 355 %signbit = ashr i8 %x, 7 356 %add = add nsw i8 %signbit, %x 357 %abs = xor i8 %add, %signbit 358 ret i8 %abs 359} 360 361; The nuw flag creates a contradiction. If the shift produces all 1s, the only 362; way for the add to not wrap is for %x to be 0, but then the shift couldn't 363; have produced all 1s. We partially optimize this. 364define i8 @shifty_abs_commute0_nuw(i8 %x) { 365; CHECK-LABEL: @shifty_abs_commute0_nuw( 366; CHECK-NEXT: [[ABS:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 0) 367; CHECK-NEXT: ret i8 [[ABS]] 368; 369 %signbit = ashr i8 %x, 7 370 %add = add nuw i8 %signbit, %x 371 %abs = xor i8 %add, %signbit 372 ret i8 %abs 373} 374 375define <2 x i8> @shifty_abs_commute1(<2 x i8> %x) { 376; CHECK-LABEL: @shifty_abs_commute1( 377; CHECK-NEXT: [[ABS:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false) 378; CHECK-NEXT: ret <2 x i8> [[ABS]] 379; 380 %signbit = ashr <2 x i8> %x, <i8 7, i8 7> 381 %add = add <2 x i8> %signbit, %x 382 %abs = xor <2 x i8> %signbit, %add 383 ret <2 x i8> %abs 384} 385 386define <2 x i8> @shifty_abs_commute2(<2 x i8> %x) { 387; CHECK-LABEL: @shifty_abs_commute2( 388; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[X:%.*]], splat (i8 3) 389; CHECK-NEXT: [[ABS:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[Y]], i1 false) 390; CHECK-NEXT: ret <2 x i8> [[ABS]] 391; 392 %y = mul <2 x i8> %x, <i8 3, i8 3> ; extra op to thwart complexity-based canonicalization 393 %signbit = ashr <2 x i8> %y, <i8 7, i8 7> 394 %add = add <2 x i8> %y, %signbit 395 %abs = xor <2 x i8> %signbit, %add 396 ret <2 x i8> %abs 397} 398 399define i8 @shifty_abs_commute3(i8 %x) { 400; CHECK-LABEL: @shifty_abs_commute3( 401; CHECK-NEXT: [[Y:%.*]] = mul i8 [[X:%.*]], 3 402; CHECK-NEXT: [[ABS:%.*]] = call i8 @llvm.abs.i8(i8 [[Y]], i1 false) 403; CHECK-NEXT: ret i8 [[ABS]] 404; 405 %y = mul i8 %x, 3 ; extra op to thwart complexity-based canonicalization 406 %signbit = ashr i8 %y, 7 407 %add = add i8 %y, %signbit 408 %abs = xor i8 %add, %signbit 409 ret i8 %abs 410} 411 412; Negative test - don't transform if it would increase instruction count. 413 414declare void @extra_use(i8) 415declare void @extra_use_i1(i1) 416 417define i8 @shifty_abs_too_many_uses(i8 %x) { 418; CHECK-LABEL: @shifty_abs_too_many_uses( 419; CHECK-NEXT: [[SIGNBIT:%.*]] = ashr i8 [[X:%.*]], 7 420; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[SIGNBIT]] 421; CHECK-NEXT: [[ABS:%.*]] = xor i8 [[ADD]], [[SIGNBIT]] 422; CHECK-NEXT: call void @extra_use(i8 [[SIGNBIT]]) 423; CHECK-NEXT: ret i8 [[ABS]] 424; 425 %signbit = ashr i8 %x, 7 426 %add = add i8 %x, %signbit 427 %abs = xor i8 %add, %signbit 428 call void @extra_use(i8 %signbit) 429 ret i8 %abs 430} 431 432; There's another way to make abs() using shift, xor, and subtract. 433; PR36036 - https://bugs.llvm.org/show_bug.cgi?id=36036 434 435define i8 @shifty_sub(i8 %x) { 436; CHECK-LABEL: @shifty_sub( 437; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) 438; CHECK-NEXT: ret i8 [[R]] 439; 440 %sh = ashr i8 %x, 7 441 %xor = xor i8 %x, %sh 442 %r = sub i8 %xor, %sh 443 ret i8 %r 444} 445 446define i8 @shifty_sub_nsw_commute(i8 %x) { 447; CHECK-LABEL: @shifty_sub_nsw_commute( 448; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 true) 449; CHECK-NEXT: ret i8 [[R]] 450; 451 %sh = ashr i8 %x, 7 452 %xor = xor i8 %sh, %x 453 %r = sub nsw i8 %xor, %sh 454 ret i8 %r 455} 456 457define <4 x i32> @shifty_sub_nuw_vec_commute(<4 x i32> %x) { 458; CHECK-LABEL: @shifty_sub_nuw_vec_commute( 459; CHECK-NEXT: [[R:%.*]] = call <4 x i32> @llvm.smax.v4i32(<4 x i32> [[X:%.*]], <4 x i32> zeroinitializer) 460; CHECK-NEXT: ret <4 x i32> [[R]] 461; 462 %sh = ashr <4 x i32> %x, <i32 31, i32 31, i32 31, i32 31> 463 %xor = xor <4 x i32> %sh, %x 464 %r = sub nuw <4 x i32> %xor, %sh 465 ret <4 x i32> %r 466} 467 468define i12 @shifty_sub_nsw_nuw(i12 %x) { 469; CHECK-LABEL: @shifty_sub_nsw_nuw( 470; CHECK-NEXT: [[R:%.*]] = call i12 @llvm.smax.i12(i12 [[X:%.*]], i12 0) 471; CHECK-NEXT: ret i12 [[R]] 472; 473 %sh = ashr i12 %x, 11 474 %xor = xor i12 %x, %sh 475 %r = sub nsw nuw i12 %xor, %sh 476 ret i12 %r 477} 478 479define i8 @negate_abs(i8 %x) { 480; CHECK-LABEL: @negate_abs( 481; CHECK-NEXT: [[S:%.*]] = call i8 @llvm.abs.i8(i8 [[X:%.*]], i1 false) 482; CHECK-NEXT: [[R:%.*]] = sub i8 0, [[S]] 483; CHECK-NEXT: ret i8 [[R]] 484; 485 %n = sub i8 0, %x 486 %c = icmp slt i8 %x, 0 487 %s = select i1 %c, i8 %n, i8 %x 488 %r = sub i8 0, %s 489 ret i8 %r 490} 491 492define <2 x i8> @negate_nabs(<2 x i8> %x) { 493; CHECK-LABEL: @negate_nabs( 494; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[X:%.*]], i1 false) 495; CHECK-NEXT: ret <2 x i8> [[TMP1]] 496; 497 %n = sub <2 x i8> zeroinitializer, %x 498 %c = icmp slt <2 x i8> %x, zeroinitializer 499 %s = select <2 x i1> %c, <2 x i8> %x, <2 x i8> %n 500 %r = sub <2 x i8> zeroinitializer, %s 501 ret <2 x i8> %r 502} 503 504define i1 @abs_must_be_positive(i32 %x) { 505; CHECK-LABEL: @abs_must_be_positive( 506; CHECK-NEXT: ret i1 true 507; 508 %negx = sub nsw i32 0, %x 509 %c = icmp sge i32 %x, 0 510 %sel = select i1 %c, i32 %x, i32 %negx 511 %c2 = icmp sge i32 %sel, 0 512 ret i1 %c2 513} 514 515define i8 @abs_swapped(i8 %a) { 516; CHECK-LABEL: @abs_swapped( 517; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]] 518; CHECK-NEXT: call void @extra_use(i8 [[NEG]]) 519; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.abs.i8(i8 [[A]], i1 false) 520; CHECK-NEXT: ret i8 [[M1]] 521; 522 %neg = sub i8 0, %a 523 call void @extra_use(i8 %neg) 524 %cmp1 = icmp sgt i8 %a, 0 525 %m1 = select i1 %cmp1, i8 %a, i8 %neg 526 ret i8 %m1 527} 528 529define i8 @nabs_swapped(i8 %a) { 530; CHECK-LABEL: @nabs_swapped( 531; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]] 532; CHECK-NEXT: call void @extra_use(i8 [[NEG]]) 533; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[A]], i1 false) 534; CHECK-NEXT: [[M2:%.*]] = sub i8 0, [[TMP1]] 535; CHECK-NEXT: ret i8 [[M2]] 536; 537 %neg = sub i8 0, %a 538 call void @extra_use(i8 %neg) 539 %cmp2 = icmp sgt i8 %a, 0 540 %m2 = select i1 %cmp2, i8 %neg, i8 %a 541 ret i8 %m2 542} 543 544define i8 @abs_different_constants(i8 %a) { 545; CHECK-LABEL: @abs_different_constants( 546; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]] 547; CHECK-NEXT: call void @extra_use(i8 [[NEG]]) 548; CHECK-NEXT: [[M1:%.*]] = call i8 @llvm.abs.i8(i8 [[A]], i1 false) 549; CHECK-NEXT: ret i8 [[M1]] 550; 551 %neg = sub i8 0, %a 552 call void @extra_use(i8 %neg) 553 %cmp1 = icmp sgt i8 %a, -1 554 %m1 = select i1 %cmp1, i8 %a, i8 %neg 555 ret i8 %m1 556} 557 558define i8 @nabs_different_constants(i8 %a) { 559; CHECK-LABEL: @nabs_different_constants( 560; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[A:%.*]] 561; CHECK-NEXT: call void @extra_use(i8 [[NEG]]) 562; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[A]], i1 false) 563; CHECK-NEXT: [[M2:%.*]] = sub i8 0, [[TMP1]] 564; CHECK-NEXT: ret i8 [[M2]] 565; 566 %neg = sub i8 0, %a 567 call void @extra_use(i8 %neg) 568 %cmp2 = icmp sgt i8 %a, -1 569 %m2 = select i1 %cmp2, i8 %neg, i8 %a 570 ret i8 %m2 571} 572 573@g = external global i64 574 575; PR45539 - https://bugs.llvm.org/show_bug.cgi?id=45539 576 577define i64 @infinite_loop_constant_expression_abs(i64 %arg) { 578; CHECK-LABEL: @infinite_loop_constant_expression_abs( 579; CHECK-NEXT: [[T:%.*]] = sub i64 ptrtoint (ptr @g to i64), [[ARG:%.*]] 580; CHECK-NEXT: [[T3:%.*]] = call i64 @llvm.abs.i64(i64 [[T]], i1 true) 581; CHECK-NEXT: ret i64 [[T3]] 582; 583 %t = sub i64 ptrtoint (ptr @g to i64), %arg 584 %t1 = icmp slt i64 %t, 0 585 %t2 = sub nsw i64 0, %t 586 %t3 = select i1 %t1, i64 %t2, i64 %t 587 ret i64 %t3 588} 589 590define i8 @abs_extra_use_icmp(i8 %x) { 591; CHECK-LABEL: @abs_extra_use_icmp( 592; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X:%.*]], 0 593; CHECK-NEXT: call void @extra_use_i1(i1 [[C]]) 594; CHECK-NEXT: [[S:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false) 595; CHECK-NEXT: ret i8 [[S]] 596; 597 %c = icmp slt i8 %x, 0 598 call void @extra_use_i1(i1 %c) 599 %n = sub i8 0, %x 600 %s = select i1 %c, i8 %n, i8 %x 601 ret i8 %s 602} 603 604define i8 @abs_extra_use_sub(i8 %x) { 605; CHECK-LABEL: @abs_extra_use_sub( 606; CHECK-NEXT: [[N:%.*]] = sub i8 0, [[X:%.*]] 607; CHECK-NEXT: call void @extra_use(i8 [[N]]) 608; CHECK-NEXT: [[S:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false) 609; CHECK-NEXT: ret i8 [[S]] 610; 611 %c = icmp slt i8 %x, 0 612 %n = sub i8 0, %x 613 call void @extra_use(i8 %n) 614 %s = select i1 %c, i8 %n, i8 %x 615 ret i8 %s 616} 617 618define i8 @abs_extra_use_icmp_sub(i8 %x) { 619; CHECK-LABEL: @abs_extra_use_icmp_sub( 620; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X:%.*]], 0 621; CHECK-NEXT: call void @extra_use_i1(i1 [[C]]) 622; CHECK-NEXT: [[N:%.*]] = sub i8 0, [[X]] 623; CHECK-NEXT: call void @extra_use(i8 [[N]]) 624; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 [[N]], i8 [[X]] 625; CHECK-NEXT: ret i8 [[S]] 626; 627 %c = icmp slt i8 %x, 0 628 call void @extra_use_i1(i1 %c) 629 %n = sub i8 0, %x 630 call void @extra_use(i8 %n) 631 %s = select i1 %c, i8 %n, i8 %x 632 ret i8 %s 633} 634 635define i8 @nabs_extra_use_icmp(i8 %x) { 636; CHECK-LABEL: @nabs_extra_use_icmp( 637; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X:%.*]], 0 638; CHECK-NEXT: call void @extra_use_i1(i1 [[C]]) 639; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false) 640; CHECK-NEXT: [[S:%.*]] = sub i8 0, [[TMP1]] 641; CHECK-NEXT: ret i8 [[S]] 642; 643 %c = icmp slt i8 %x, 0 644 call void @extra_use_i1(i1 %c) 645 %n = sub i8 0, %x 646 %s = select i1 %c, i8 %x, i8 %n 647 ret i8 %s 648} 649 650define i8 @nabs_extra_use_sub(i8 %x) { 651; CHECK-LABEL: @nabs_extra_use_sub( 652; CHECK-NEXT: [[N:%.*]] = sub i8 0, [[X:%.*]] 653; CHECK-NEXT: call void @extra_use(i8 [[N]]) 654; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false) 655; CHECK-NEXT: [[S:%.*]] = sub i8 0, [[TMP1]] 656; CHECK-NEXT: ret i8 [[S]] 657; 658 %c = icmp slt i8 %x, 0 659 %n = sub i8 0, %x 660 call void @extra_use(i8 %n) 661 %s = select i1 %c, i8 %x, i8 %n 662 ret i8 %s 663} 664 665define i8 @nabs_extra_use_icmp_sub(i8 %x) { 666; CHECK-LABEL: @nabs_extra_use_icmp_sub( 667; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X:%.*]], 0 668; CHECK-NEXT: call void @extra_use_i1(i1 [[C]]) 669; CHECK-NEXT: [[N:%.*]] = sub i8 0, [[X]] 670; CHECK-NEXT: call void @extra_use(i8 [[N]]) 671; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 [[X]], i8 [[N]] 672; CHECK-NEXT: ret i8 [[S]] 673; 674 %c = icmp slt i8 %x, 0 675 call void @extra_use_i1(i1 %c) 676 %n = sub i8 0, %x 677 call void @extra_use(i8 %n) 678 %s = select i1 %c, i8 %x, i8 %n 679 ret i8 %s 680} 681 682; TODO: negate-of-abs-diff 683 684define i32 @nabs_diff_signed_slt(i32 %a, i32 %b) { 685; CHECK-LABEL: @nabs_diff_signed_slt( 686; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] 687; CHECK-NEXT: [[SUB_BA:%.*]] = sub nsw i32 [[B]], [[A]] 688; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i32 [[A]], [[B]] 689; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB_AB]], i32 [[SUB_BA]] 690; CHECK-NEXT: ret i32 [[COND]] 691; 692 %cmp = icmp slt i32 %a, %b 693 %sub_ba = sub nsw i32 %b, %a 694 %sub_ab = sub nsw i32 %a, %b 695 %cond = select i1 %cmp, i32 %sub_ab, i32 %sub_ba 696 ret i32 %cond 697} 698 699; TODO: negate-of-abs-diff 700 701define <2 x i8> @nabs_diff_signed_sle(<2 x i8> %a, <2 x i8> %b) { 702; CHECK-LABEL: @nabs_diff_signed_sle( 703; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt <2 x i8> [[A:%.*]], [[B:%.*]] 704; CHECK-NEXT: [[SUB_BA:%.*]] = sub nsw <2 x i8> [[B]], [[A]] 705; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw <2 x i8> [[A]], [[B]] 706; CHECK-NEXT: [[COND:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i8> [[SUB_BA]], <2 x i8> [[SUB_AB]] 707; CHECK-NEXT: ret <2 x i8> [[COND]] 708; 709 %cmp = icmp sle <2 x i8> %a, %b 710 %sub_ba = sub nsw <2 x i8> %b, %a 711 %sub_ab = sub nsw <2 x i8> %a, %b 712 %cond = select <2 x i1> %cmp, <2 x i8> %sub_ab, <2 x i8> %sub_ba 713 ret <2 x i8> %cond 714} 715 716define i8 @abs_diff_signed_sgt(i8 %a, i8 %b) { 717; CHECK-LABEL: @abs_diff_signed_sgt( 718; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]] 719; CHECK-NEXT: call void @extra_use(i8 [[SUB_AB]]) 720; CHECK-NEXT: [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true) 721; CHECK-NEXT: ret i8 [[COND]] 722; 723 %cmp = icmp sgt i8 %a, %b 724 %sub_ba = sub nsw i8 %b, %a 725 %sub_ab = sub nsw i8 %a, %b 726 call void @extra_use(i8 %sub_ab) 727 %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba 728 ret i8 %cond 729} 730 731define i8 @abs_diff_signed_sge(i8 %a, i8 %b) { 732; CHECK-LABEL: @abs_diff_signed_sge( 733; CHECK-NEXT: [[SUB_BA:%.*]] = sub nsw i8 [[B:%.*]], [[A:%.*]] 734; CHECK-NEXT: call void @extra_use(i8 [[SUB_BA]]) 735; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i8 [[A]], [[B]] 736; CHECK-NEXT: call void @extra_use(i8 [[SUB_AB]]) 737; CHECK-NEXT: [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true) 738; CHECK-NEXT: ret i8 [[COND]] 739; 740 %cmp = icmp sge i8 %a, %b 741 %sub_ba = sub nsw i8 %b, %a 742 call void @extra_use(i8 %sub_ba) 743 %sub_ab = sub nsw i8 %a, %b 744 call void @extra_use(i8 %sub_ab) 745 %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba 746 ret i8 %cond 747} 748 749; negative test - need nsw 750 751define i32 @abs_diff_signed_slt_no_nsw(i32 %a, i32 %b) { 752; CHECK-LABEL: @abs_diff_signed_slt_no_nsw( 753; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] 754; CHECK-NEXT: [[SUB_BA:%.*]] = sub i32 [[B]], [[A]] 755; CHECK-NEXT: [[SUB_AB:%.*]] = sub i32 [[A]], [[B]] 756; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB_AB]], i32 [[SUB_BA]] 757; CHECK-NEXT: ret i32 [[COND]] 758; 759 %cmp = icmp slt i32 %a, %b 760 %sub_ba = sub i32 %b, %a 761 %sub_ab = sub i32 %a, %b 762 %cond = select i1 %cmp, i32 %sub_ab, i32 %sub_ba 763 ret i32 %cond 764} 765 766; bonus nuw - it's fine to match the pattern, but nuw can't propagate 767 768define i8 @abs_diff_signed_sgt_nsw_nuw(i8 %a, i8 %b) { 769; CHECK-LABEL: @abs_diff_signed_sgt_nsw_nuw( 770; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]] 771; CHECK-NEXT: [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true) 772; CHECK-NEXT: ret i8 [[COND]] 773; 774 %cmp = icmp sgt i8 %a, %b 775 %sub_ba = sub nsw nuw i8 %b, %a 776 %sub_ab = sub nsw nuw i8 %a, %b 777 %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba 778 ret i8 %cond 779} 780 781; this is absolute diff, but nuw can't propagate and nsw can be set. 782 783define i8 @abs_diff_signed_sgt_nuw(i8 %a, i8 %b) { 784; CHECK-LABEL: @abs_diff_signed_sgt_nuw( 785; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i8 [[A:%.*]], [[B:%.*]] 786; CHECK-NEXT: [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true) 787; CHECK-NEXT: ret i8 [[COND]] 788; 789 %cmp = icmp sgt i8 %a, %b 790 %sub_ba = sub nuw i8 %b, %a 791 %sub_ab = sub nuw i8 %a, %b 792 %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba 793 ret i8 %cond 794} 795 796; same as above 797 798define i8 @abs_diff_signed_sgt_nuw_extra_use1(i8 %a, i8 %b) { 799; CHECK-LABEL: @abs_diff_signed_sgt_nuw_extra_use1( 800; CHECK-NEXT: [[SUB_BA:%.*]] = sub nuw i8 [[B:%.*]], [[A:%.*]] 801; CHECK-NEXT: call void @extra_use(i8 [[SUB_BA]]) 802; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i8 [[A]], [[B]] 803; CHECK-NEXT: [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true) 804; CHECK-NEXT: ret i8 [[COND]] 805; 806 %cmp = icmp sgt i8 %a, %b 807 %sub_ba = sub nuw i8 %b, %a 808 call void @extra_use(i8 %sub_ba) 809 %sub_ab = sub nuw i8 %a, %b 810 %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba 811 ret i8 %cond 812} 813 814; nuw can't propagate, and the extra use prevents applying nsw 815 816define i8 @abs_diff_signed_sgt_nuw_extra_use2(i8 %a, i8 %b) { 817; CHECK-LABEL: @abs_diff_signed_sgt_nuw_extra_use2( 818; CHECK-NEXT: [[SUB_AB:%.*]] = sub i8 [[A:%.*]], [[B:%.*]] 819; CHECK-NEXT: call void @extra_use(i8 [[SUB_AB]]) 820; CHECK-NEXT: [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true) 821; CHECK-NEXT: ret i8 [[COND]] 822; 823 %cmp = icmp sgt i8 %a, %b 824 %sub_ba = sub nuw i8 %b, %a 825 %sub_ab = sub nuw i8 %a, %b 826 call void @extra_use(i8 %sub_ab) 827 %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba 828 ret i8 %cond 829} 830 831; same as above 832 833define i8 @abs_diff_signed_sgt_nuw_extra_use3(i8 %a, i8 %b) { 834; CHECK-LABEL: @abs_diff_signed_sgt_nuw_extra_use3( 835; CHECK-NEXT: [[SUB_BA:%.*]] = sub nuw i8 [[B:%.*]], [[A:%.*]] 836; CHECK-NEXT: call void @extra_use(i8 [[SUB_BA]]) 837; CHECK-NEXT: [[SUB_AB:%.*]] = sub i8 [[A]], [[B]] 838; CHECK-NEXT: call void @extra_use(i8 [[SUB_AB]]) 839; CHECK-NEXT: [[COND:%.*]] = call i8 @llvm.abs.i8(i8 [[SUB_AB]], i1 true) 840; CHECK-NEXT: ret i8 [[COND]] 841; 842 %cmp = icmp sgt i8 %a, %b 843 %sub_ba = sub nuw i8 %b, %a 844 call void @extra_use(i8 %sub_ba) 845 %sub_ab = sub nuw i8 %a, %b 846 call void @extra_use(i8 %sub_ab) 847 %cond = select i1 %cmp, i8 %sub_ab, i8 %sub_ba 848 ret i8 %cond 849} 850 851; negative test - wrong predicate 852 853define i32 @abs_diff_signed_slt_swap_wrong_pred1(i32 %a, i32 %b) { 854; CHECK-LABEL: @abs_diff_signed_slt_swap_wrong_pred1( 855; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i32 [[A:%.*]], [[B:%.*]] 856; CHECK-NEXT: ret i32 [[SUB_AB]] 857; 858 %cmp = icmp eq i32 %a, %b 859 %sub_ba = sub nsw i32 %b, %a 860 %sub_ab = sub nsw i32 %a, %b 861 %cond = select i1 %cmp, i32 %sub_ba, i32 %sub_ab 862 ret i32 %cond 863} 864 865; negative test - wrong predicate 866 867define i32 @abs_diff_signed_slt_swap_wrong_pred2(i32 %a, i32 %b) { 868; CHECK-LABEL: @abs_diff_signed_slt_swap_wrong_pred2( 869; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]] 870; CHECK-NEXT: [[SUB_BA:%.*]] = sub nsw i32 [[B]], [[A]] 871; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i32 [[A]], [[B]] 872; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB_BA]], i32 [[SUB_AB]] 873; CHECK-NEXT: ret i32 [[COND]] 874; 875 %cmp = icmp ult i32 %a, %b 876 %sub_ba = sub nsw i32 %b, %a 877 %sub_ab = sub nsw i32 %a, %b 878 %cond = select i1 %cmp, i32 %sub_ba, i32 %sub_ab 879 ret i32 %cond 880} 881 882; negative test - need common operands 883 884define i32 @abs_diff_signed_slt_swap_wrong_op(i32 %a, i32 %b, i32 %z) { 885; CHECK-LABEL: @abs_diff_signed_slt_swap_wrong_op( 886; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 887; CHECK-NEXT: [[SUB_BZ:%.*]] = sub nsw i32 [[B]], [[Z:%.*]] 888; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i32 [[A]], [[B]] 889; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB_BZ]], i32 [[SUB_AB]] 890; CHECK-NEXT: ret i32 [[COND]] 891; 892 %cmp = icmp eq i32 %a, %b 893 %sub_bz = sub nsw i32 %b, %z 894 %sub_ab = sub nsw i32 %a, %b 895 %cond = select i1 %cmp, i32 %sub_bz, i32 %sub_ab 896 ret i32 %cond 897} 898 899define i32 @abs_diff_signed_slt_swap(i32 %a, i32 %b) { 900; CHECK-LABEL: @abs_diff_signed_slt_swap( 901; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i32 [[A:%.*]], [[B:%.*]] 902; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB_AB]], i1 true) 903; CHECK-NEXT: ret i32 [[COND]] 904; 905 %cmp = icmp slt i32 %a, %b 906 %sub_ba = sub nsw i32 %b, %a 907 %sub_ab = sub nsw i32 %a, %b 908 %cond = select i1 %cmp, i32 %sub_ba, i32 %sub_ab 909 ret i32 %cond 910} 911 912define <2 x i8> @abs_diff_signed_sle_swap(<2 x i8> %a, <2 x i8> %b) { 913; CHECK-LABEL: @abs_diff_signed_sle_swap( 914; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw <2 x i8> [[A:%.*]], [[B:%.*]] 915; CHECK-NEXT: [[COND:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[SUB_AB]], i1 true) 916; CHECK-NEXT: ret <2 x i8> [[COND]] 917; 918 %cmp = icmp sle <2 x i8> %a, %b 919 %sub_ba = sub nsw <2 x i8> %b, %a 920 %sub_ab = sub nsw <2 x i8> %a, %b 921 %cond = select <2 x i1> %cmp, <2 x i8> %sub_ba, <2 x i8> %sub_ab 922 ret <2 x i8> %cond 923} 924 925; TODO: negate-of-abs-diff 926 927define i8 @nabs_diff_signed_sgt_swap(i8 %a, i8 %b) { 928; CHECK-LABEL: @nabs_diff_signed_sgt_swap( 929; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], [[B:%.*]] 930; CHECK-NEXT: [[SUB_BA:%.*]] = sub nsw i8 [[B]], [[A]] 931; CHECK-NEXT: call void @extra_use(i8 [[SUB_BA]]) 932; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i8 [[A]], [[B]] 933; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 [[SUB_BA]], i8 [[SUB_AB]] 934; CHECK-NEXT: ret i8 [[COND]] 935; 936 %cmp = icmp sgt i8 %a, %b 937 %sub_ba = sub nsw i8 %b, %a 938 call void @extra_use(i8 %sub_ba) 939 %sub_ab = sub nsw i8 %a, %b 940 %cond = select i1 %cmp, i8 %sub_ba, i8 %sub_ab 941 ret i8 %cond 942} 943 944; TODO: negate-of-abs-diff, but too many uses? 945 946define i8 @nabs_diff_signed_sge_swap(i8 %a, i8 %b) { 947; CHECK-LABEL: @nabs_diff_signed_sge_swap( 948; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i8 [[A:%.*]], [[B:%.*]] 949; CHECK-NEXT: [[SUB_BA:%.*]] = sub nsw i8 [[B]], [[A]] 950; CHECK-NEXT: call void @extra_use(i8 [[SUB_BA]]) 951; CHECK-NEXT: [[SUB_AB:%.*]] = sub nsw i8 [[A]], [[B]] 952; CHECK-NEXT: call void @extra_use(i8 [[SUB_AB]]) 953; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP_NOT]], i8 [[SUB_AB]], i8 [[SUB_BA]] 954; CHECK-NEXT: ret i8 [[COND]] 955; 956 %cmp = icmp sge i8 %a, %b 957 %sub_ba = sub nsw i8 %b, %a 958 call void @extra_use(i8 %sub_ba) 959 %sub_ab = sub nsw i8 %a, %b 960 call void @extra_use(i8 %sub_ab) 961 %cond = select i1 %cmp, i8 %sub_ba, i8 %sub_ab 962 ret i8 %cond 963} 964 965; negative test - need nsw 966 967define i32 @abs_diff_signed_slt_no_nsw_swap(i32 %a, i32 %b) { 968; CHECK-LABEL: @abs_diff_signed_slt_no_nsw_swap( 969; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]] 970; CHECK-NEXT: [[SUB_BA:%.*]] = sub nsw i32 [[B]], [[A]] 971; CHECK-NEXT: [[SUB_AB:%.*]] = sub i32 [[A]], [[B]] 972; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB_BA]], i32 [[SUB_AB]] 973; CHECK-NEXT: ret i32 [[COND]] 974; 975 %cmp = icmp slt i32 %a, %b 976 %sub_ba = sub nsw i32 %b, %a 977 %sub_ab = sub i32 %a, %b 978 %cond = select i1 %cmp, i32 %sub_ba, i32 %sub_ab 979 ret i32 %cond 980} 981