1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -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: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0 16; CHECK-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[X]] 17; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i32 [[NEG]], i32 [[X]] 18; CHECK-NEXT: ret i32 [[TMP2]] 19; 20 %ret = call i32 @abs(i32 %x) 21 ret i32 %ret 22} 23 24define i64 @test_labs(i64 %x) { 25; CHECK-LABEL: @test_labs( 26; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[X:%.*]], 0 27; CHECK-NEXT: [[NEG:%.*]] = sub nsw i64 0, [[X]] 28; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i64 [[NEG]], i64 [[X]] 29; CHECK-NEXT: ret i64 [[TMP2]] 30; 31 %ret = call i64 @labs(i64 %x) 32 ret i64 %ret 33} 34 35define i64 @test_llabs(i64 %x) { 36; CHECK-LABEL: @test_llabs( 37; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[X:%.*]], 0 38; CHECK-NEXT: [[NEG:%.*]] = sub nsw i64 0, [[X]] 39; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i64 [[NEG]], i64 [[X]] 40; CHECK-NEXT: ret i64 [[TMP2]] 41; 42 %ret = call i64 @llabs(i64 %x) 43 ret i64 %ret 44} 45 46; We have a canonical form of abs to make CSE easier. 47 48define i8 @abs_canonical_1(i8 %x) { 49; CHECK-LABEL: @abs_canonical_1( 50; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0 51; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[X]] 52; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i8 [[NEG]], i8 [[X]] 53; CHECK-NEXT: ret i8 [[ABS]] 54; 55 %cmp = icmp sgt i8 %x, 0 56 %neg = sub i8 0, %x 57 %abs = select i1 %cmp, i8 %x, i8 %neg 58 ret i8 %abs 59} 60 61; Vectors should work too. 62 63define <2 x i8> @abs_canonical_2(<2 x i8> %x) { 64; CHECK-LABEL: @abs_canonical_2( 65; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer 66; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X]] 67; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[NEG]], <2 x i8> [[X]] 68; CHECK-NEXT: ret <2 x i8> [[ABS]] 69; 70 %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 -1> 71 %neg = sub <2 x i8> zeroinitializer, %x 72 %abs = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> %neg 73 ret <2 x i8> %abs 74} 75 76; Even if a constant has undef elements. 77 78define <2 x i8> @abs_canonical_2_vec_undef_elts(<2 x i8> %x) { 79; CHECK-LABEL: @abs_canonical_2_vec_undef_elts( 80; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer 81; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X]] 82; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[NEG]], <2 x i8> [[X]] 83; CHECK-NEXT: ret <2 x i8> [[ABS]] 84; 85 %cmp = icmp sgt <2 x i8> %x, <i8 undef, i8 -1> 86 %neg = sub <2 x i8> zeroinitializer, %x 87 %abs = select <2 x i1> %cmp, <2 x i8> %x, <2 x i8> %neg 88 ret <2 x i8> %abs 89} 90 91; NSW should not change. 92 93define i8 @abs_canonical_3(i8 %x) { 94; CHECK-LABEL: @abs_canonical_3( 95; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0 96; CHECK-NEXT: [[NEG:%.*]] = sub nsw i8 0, [[X]] 97; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i8 [[NEG]], i8 [[X]] 98; CHECK-NEXT: ret i8 [[ABS]] 99; 100 %cmp = icmp slt i8 %x, 0 101 %neg = sub nsw i8 0, %x 102 %abs = select i1 %cmp, i8 %neg, i8 %x 103 ret i8 %abs 104} 105 106define i8 @abs_canonical_4(i8 %x) { 107; CHECK-LABEL: @abs_canonical_4( 108; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0 109; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[X]] 110; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i8 [[NEG]], i8 [[X]] 111; CHECK-NEXT: ret i8 [[ABS]] 112; 113 %cmp = icmp slt i8 %x, 1 114 %neg = sub i8 0, %x 115 %abs = select i1 %cmp, i8 %neg, i8 %x 116 ret i8 %abs 117} 118 119define i32 @abs_canonical_5(i8 %x) { 120; CHECK-LABEL: @abs_canonical_5( 121; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0 122; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[X]] to i32 123; CHECK-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[CONV]] 124; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEG]], i32 [[CONV]] 125; CHECK-NEXT: ret i32 [[ABS]] 126; 127 %cmp = icmp sgt i8 %x, 0 128 %conv = sext i8 %x to i32 129 %neg = sub i32 0, %conv 130 %abs = select i1 %cmp, i32 %conv, i32 %neg 131 ret i32 %abs 132} 133 134define i32 @abs_canonical_6(i32 %a, i32 %b) { 135; CHECK-LABEL: @abs_canonical_6( 136; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 137; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0 138; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]] 139; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP2]], i32 [[TMP1]] 140; CHECK-NEXT: ret i32 [[ABS]] 141; 142 %tmp1 = sub i32 %a, %b 143 %cmp = icmp sgt i32 %tmp1, -1 144 %tmp2 = sub i32 %b, %a 145 %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2 146 ret i32 %abs 147} 148 149define <2 x i8> @abs_canonical_7(<2 x i8> %a, <2 x i8 > %b) { 150; CHECK-LABEL: @abs_canonical_7( 151; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]] 152; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[TMP1]], zeroinitializer 153; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]] 154; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP2]], <2 x i8> [[TMP1]] 155; CHECK-NEXT: ret <2 x i8> [[ABS]] 156; 157 158 %tmp1 = sub <2 x i8> %a, %b 159 %cmp = icmp sgt <2 x i8> %tmp1, <i8 -1, i8 -1> 160 %tmp2 = sub <2 x i8> %b, %a 161 %abs = select <2 x i1> %cmp, <2 x i8> %tmp1, <2 x i8> %tmp2 162 ret <2 x i8> %abs 163} 164 165define i32 @abs_canonical_8(i32 %a) { 166; CHECK-LABEL: @abs_canonical_8( 167; CHECK-NEXT: [[TMP:%.*]] = sub i32 0, [[A:%.*]] 168; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 169; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP]], i32 [[A]] 170; CHECK-NEXT: ret i32 [[ABS]] 171; 172 %tmp = sub i32 0, %a 173 %cmp = icmp slt i32 %tmp, 0 174 %abs = select i1 %cmp, i32 %a, i32 %tmp 175 ret i32 %abs 176} 177 178define i32 @abs_canonical_9(i32 %a, i32 %b) { 179; CHECK-LABEL: @abs_canonical_9( 180; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 181; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1 182; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[B]], [[A]] 183; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[TMP2]] 184; CHECK-NEXT: [[ADD:%.*]] = add i32 [[ABS]], [[TMP2]] 185; CHECK-NEXT: ret i32 [[ADD]] 186; 187 %tmp1 = sub i32 %a, %b 188 %cmp = icmp sgt i32 %tmp1, -1 189 %tmp2 = sub i32 %b, %a 190 %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2 191 %add = add i32 %abs, %tmp2 ; increase use count for %tmp2. 192 ret i32 %add 193} 194 195define i32 @abs_canonical_10(i32 %a, i32 %b) { 196; CHECK-LABEL: @abs_canonical_10( 197; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 198; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0 199; CHECK-NEXT: [[NEGTMP:%.*]] = sub i32 0, [[TMP1]] 200; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGTMP]], i32 [[TMP1]] 201; CHECK-NEXT: ret i32 [[ABS]] 202; 203 %tmp2 = sub i32 %b, %a 204 %tmp1 = sub i32 %a, %b 205 %cmp = icmp sgt i32 %tmp1, -1 206 %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2 207 ret i32 %abs 208} 209 210; We have a canonical form of nabs to make CSE easier. 211 212define i8 @nabs_canonical_1(i8 %x) { 213; CHECK-LABEL: @nabs_canonical_1( 214; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0 215; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[X]] 216; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[NEG]] 217; CHECK-NEXT: ret i8 [[ABS]] 218; 219 %cmp = icmp sgt i8 %x, 0 220 %neg = sub i8 0, %x 221 %abs = select i1 %cmp, i8 %neg, i8 %x 222 ret i8 %abs 223} 224 225; Vectors should work too. 226 227define <2 x i8> @nabs_canonical_2(<2 x i8> %x) { 228; CHECK-LABEL: @nabs_canonical_2( 229; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer 230; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X]] 231; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[X]], <2 x i8> [[NEG]] 232; CHECK-NEXT: ret <2 x i8> [[ABS]] 233; 234 %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 -1> 235 %neg = sub <2 x i8> zeroinitializer, %x 236 %abs = select <2 x i1> %cmp, <2 x i8> %neg, <2 x i8> %x 237 ret <2 x i8> %abs 238} 239 240; Even if a constant has undef elements. 241 242define <2 x i8> @nabs_canonical_2_vec_undef_elts(<2 x i8> %x) { 243; CHECK-LABEL: @nabs_canonical_2_vec_undef_elts( 244; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer 245; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X]] 246; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[X]], <2 x i8> [[NEG]] 247; CHECK-NEXT: ret <2 x i8> [[ABS]] 248; 249 %cmp = icmp sgt <2 x i8> %x, <i8 -1, i8 undef> 250 %neg = sub <2 x i8> zeroinitializer, %x 251 %abs = select <2 x i1> %cmp, <2 x i8> %neg, <2 x i8> %x 252 ret <2 x i8> %abs 253} 254 255; NSW should not change. 256 257define i8 @nabs_canonical_3(i8 %x) { 258; CHECK-LABEL: @nabs_canonical_3( 259; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0 260; CHECK-NEXT: [[NEG:%.*]] = sub nsw i8 0, [[X]] 261; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[NEG]] 262; CHECK-NEXT: ret i8 [[ABS]] 263; 264 %cmp = icmp slt i8 %x, 0 265 %neg = sub nsw i8 0, %x 266 %abs = select i1 %cmp, i8 %x, i8 %neg 267 ret i8 %abs 268} 269 270define i8 @nabs_canonical_4(i8 %x) { 271; CHECK-LABEL: @nabs_canonical_4( 272; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0 273; CHECK-NEXT: [[NEG:%.*]] = sub i8 0, [[X]] 274; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i8 [[X]], i8 [[NEG]] 275; CHECK-NEXT: ret i8 [[ABS]] 276; 277 %cmp = icmp slt i8 %x, 1 278 %neg = sub i8 0, %x 279 %abs = select i1 %cmp, i8 %x, i8 %neg 280 ret i8 %abs 281} 282 283define i32 @nabs_canonical_5(i8 %x) { 284; CHECK-LABEL: @nabs_canonical_5( 285; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], 0 286; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[X]] to i32 287; CHECK-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[CONV]] 288; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[CONV]], i32 [[NEG]] 289; CHECK-NEXT: ret i32 [[ABS]] 290; 291 %cmp = icmp sgt i8 %x, 0 292 %conv = sext i8 %x to i32 293 %neg = sub i32 0, %conv 294 %abs = select i1 %cmp, i32 %neg, i32 %conv 295 ret i32 %abs 296} 297 298define i32 @nabs_canonical_6(i32 %a, i32 %b) { 299; CHECK-LABEL: @nabs_canonical_6( 300; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 301; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0 302; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]] 303; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[TMP2]] 304; CHECK-NEXT: ret i32 [[ABS]] 305; 306 %tmp1 = sub i32 %a, %b 307 %cmp = icmp sgt i32 %tmp1, -1 308 %tmp2 = sub i32 %b, %a 309 %abs = select i1 %cmp, i32 %tmp2, i32 %tmp1 310 ret i32 %abs 311} 312 313define <2 x i8> @nabs_canonical_7(<2 x i8> %a, <2 x i8 > %b) { 314; CHECK-LABEL: @nabs_canonical_7( 315; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]] 316; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[TMP1]], zeroinitializer 317; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]] 318; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP1]], <2 x i8> [[TMP2]] 319; CHECK-NEXT: ret <2 x i8> [[ABS]] 320; 321 %tmp1 = sub <2 x i8> %a, %b 322 %cmp = icmp sgt <2 x i8> %tmp1, <i8 -1, i8 -1> 323 %tmp2 = sub <2 x i8> %b, %a 324 %abs = select <2 x i1> %cmp, <2 x i8> %tmp2, <2 x i8> %tmp1 325 ret <2 x i8> %abs 326} 327 328define i32 @nabs_canonical_8(i32 %a) { 329; CHECK-LABEL: @nabs_canonical_8( 330; CHECK-NEXT: [[TMP:%.*]] = sub i32 0, [[A:%.*]] 331; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0 332; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[TMP]] 333; CHECK-NEXT: ret i32 [[ABS]] 334; 335 %tmp = sub i32 0, %a 336 %cmp = icmp slt i32 %tmp, 0 337 %abs = select i1 %cmp, i32 %tmp, i32 %a 338 ret i32 %abs 339} 340 341define i32 @nabs_canonical_9(i32 %a, i32 %b) { 342; CHECK-LABEL: @nabs_canonical_9( 343; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 344; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1 345; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[B]], [[A]] 346; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP2]], i32 [[TMP1]] 347; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP2]], [[ABS]] 348; CHECK-NEXT: ret i32 [[ADD]] 349; 350 %tmp1 = sub i32 %a, %b 351 %cmp = icmp sgt i32 %tmp1, -1 352 %tmp2 = sub i32 %b, %a 353 %abs = select i1 %cmp, i32 %tmp2, i32 %tmp1 354 %add = add i32 %tmp2, %abs ; increase use count for %tmp2 355 ret i32 %add 356} 357 358define i32 @nabs_canonical_10(i32 %a, i32 %b) { 359; CHECK-LABEL: @nabs_canonical_10( 360; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]] 361; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0 362; CHECK-NEXT: [[NEGTMP:%.*]] = sub i32 0, [[TMP1]] 363; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[NEGTMP]] 364; CHECK-NEXT: ret i32 [[ABS]] 365; 366 %tmp2 = sub i32 %b, %a 367 %tmp1 = sub i32 %a, %b 368 %cmp = icmp slt i32 %tmp1, 1 369 %abs = select i1 %cmp, i32 %tmp1, i32 %tmp2 370 ret i32 %abs 371} 372 373; The following 5 tests use a shift+add+xor to implement abs(): 374; B = ashr i8 A, 7 -- smear the sign bit. 375; xor (add A, B), B -- add -1 and flip bits if negative 376 377define i8 @shifty_abs_commute0(i8 %x) { 378; CHECK-LABEL: @shifty_abs_commute0( 379; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0 380; CHECK-NEXT: [[TMP2:%.*]] = sub i8 0, [[X]] 381; CHECK-NEXT: [[ABS:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]] 382; CHECK-NEXT: ret i8 [[ABS]] 383; 384 %signbit = ashr i8 %x, 7 385 %add = add i8 %signbit, %x 386 %abs = xor i8 %add, %signbit 387 ret i8 %abs 388} 389 390define i8 @shifty_abs_commute0_nsw(i8 %x) { 391; CHECK-LABEL: @shifty_abs_commute0_nsw( 392; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0 393; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i8 0, [[X]] 394; CHECK-NEXT: [[ABS:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]] 395; CHECK-NEXT: ret i8 [[ABS]] 396; 397 %signbit = ashr i8 %x, 7 398 %add = add nsw i8 %signbit, %x 399 %abs = xor i8 %add, %signbit 400 ret i8 %abs 401} 402 403; The nuw flag creates a contradiction. If the shift produces all 1s, the only 404; way for the add to not wrap is for %x to be 0, but then the shift couldn't 405; have produced all 1s. We partially optimize this. 406define i8 @shifty_abs_commute0_nuw(i8 %x) { 407; CHECK-LABEL: @shifty_abs_commute0_nuw( 408; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[X:%.*]], 0 409; CHECK-NEXT: [[ABS:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 0 410; CHECK-NEXT: ret i8 [[ABS]] 411; 412 %signbit = ashr i8 %x, 7 413 %add = add nuw i8 %signbit, %x 414 %abs = xor i8 %add, %signbit 415 ret i8 %abs 416} 417 418define <2 x i8> @shifty_abs_commute1(<2 x i8> %x) { 419; CHECK-LABEL: @shifty_abs_commute1( 420; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer 421; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[X]] 422; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[TMP1]], <2 x i8> [[TMP2]], <2 x i8> [[X]] 423; CHECK-NEXT: ret <2 x i8> [[ABS]] 424; 425 %signbit = ashr <2 x i8> %x, <i8 7, i8 7> 426 %add = add <2 x i8> %signbit, %x 427 %abs = xor <2 x i8> %signbit, %add 428 ret <2 x i8> %abs 429} 430 431define <2 x i8> @shifty_abs_commute2(<2 x i8> %x) { 432; CHECK-LABEL: @shifty_abs_commute2( 433; CHECK-NEXT: [[Y:%.*]] = mul <2 x i8> [[X:%.*]], <i8 3, i8 3> 434; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i8> [[Y]], zeroinitializer 435; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[Y]] 436; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[TMP1]], <2 x i8> [[TMP2]], <2 x i8> [[Y]] 437; CHECK-NEXT: ret <2 x i8> [[ABS]] 438; 439 %y = mul <2 x i8> %x, <i8 3, i8 3> ; extra op to thwart complexity-based canonicalization 440 %signbit = ashr <2 x i8> %y, <i8 7, i8 7> 441 %add = add <2 x i8> %y, %signbit 442 %abs = xor <2 x i8> %signbit, %add 443 ret <2 x i8> %abs 444} 445 446define i8 @shifty_abs_commute3(i8 %x) { 447; CHECK-LABEL: @shifty_abs_commute3( 448; CHECK-NEXT: [[Y:%.*]] = mul i8 [[X:%.*]], 3 449; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[Y]], 0 450; CHECK-NEXT: [[TMP2:%.*]] = sub i8 0, [[Y]] 451; CHECK-NEXT: [[ABS:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[Y]] 452; CHECK-NEXT: ret i8 [[ABS]] 453; 454 %y = mul i8 %x, 3 ; extra op to thwart complexity-based canonicalization 455 %signbit = ashr i8 %y, 7 456 %add = add i8 %y, %signbit 457 %abs = xor i8 %add, %signbit 458 ret i8 %abs 459} 460 461; Negative test - don't transform if it would increase instruction count. 462 463declare void @extra_use(i8) 464 465define i8 @shifty_abs_too_many_uses(i8 %x) { 466; CHECK-LABEL: @shifty_abs_too_many_uses( 467; CHECK-NEXT: [[SIGNBIT:%.*]] = ashr i8 [[X:%.*]], 7 468; CHECK-NEXT: [[ADD:%.*]] = add i8 [[SIGNBIT]], [[X]] 469; CHECK-NEXT: [[ABS:%.*]] = xor i8 [[ADD]], [[SIGNBIT]] 470; CHECK-NEXT: call void @extra_use(i8 [[SIGNBIT]]) 471; CHECK-NEXT: ret i8 [[ABS]] 472; 473 %signbit = ashr i8 %x, 7 474 %add = add i8 %x, %signbit 475 %abs = xor i8 %add, %signbit 476 call void @extra_use(i8 %signbit) 477 ret i8 %abs 478} 479 480; There's another way to make abs() using shift, xor, and subtract. 481; PR36036 - https://bugs.llvm.org/show_bug.cgi?id=36036 482 483define i8 @shifty_sub(i8 %x) { 484; CHECK-LABEL: @shifty_sub( 485; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0 486; CHECK-NEXT: [[TMP2:%.*]] = sub i8 0, [[X]] 487; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]] 488; CHECK-NEXT: ret i8 [[R]] 489; 490 %sh = ashr i8 %x, 7 491 %xor = xor i8 %x, %sh 492 %r = sub i8 %xor, %sh 493 ret i8 %r 494} 495 496define i8 @shifty_sub_nsw_commute(i8 %x) { 497; CHECK-LABEL: @shifty_sub_nsw_commute( 498; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0 499; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i8 0, [[X]] 500; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i8 [[TMP2]], i8 [[X]] 501; CHECK-NEXT: ret i8 [[R]] 502; 503 %sh = ashr i8 %x, 7 504 %xor = xor i8 %sh, %x 505 %r = sub nsw i8 %xor, %sh 506 ret i8 %r 507} 508 509define <4 x i32> @shifty_sub_nuw_vec_commute(<4 x i32> %x) { 510; CHECK-LABEL: @shifty_sub_nuw_vec_commute( 511; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i32> [[X:%.*]], zeroinitializer 512; CHECK-NEXT: [[R:%.*]] = select <4 x i1> [[TMP1]], <4 x i32> [[X]], <4 x i32> zeroinitializer 513; CHECK-NEXT: ret <4 x i32> [[R]] 514; 515 %sh = ashr <4 x i32> %x, <i32 31, i32 31, i32 31, i32 31> 516 %xor = xor <4 x i32> %sh, %x 517 %r = sub nuw <4 x i32> %xor, %sh 518 ret <4 x i32> %r 519} 520 521define i12 @shifty_sub_nsw_nuw(i12 %x) { 522; CHECK-LABEL: @shifty_sub_nsw_nuw( 523; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i12 [[X:%.*]], 0 524; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i12 [[X]], i12 0 525; CHECK-NEXT: ret i12 [[R]] 526; 527 %sh = ashr i12 %x, 11 528 %xor = xor i12 %x, %sh 529 %r = sub nsw nuw i12 %xor, %sh 530 ret i12 %r 531} 532 533define i8 @negate_abs(i8 %x) { 534; CHECK-LABEL: @negate_abs( 535; CHECK-NEXT: [[N:%.*]] = sub i8 0, [[X:%.*]] 536; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X]], 0 537; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i8 [[X]], i8 [[N]] 538; CHECK-NEXT: ret i8 [[S]] 539; 540 %n = sub i8 0, %x 541 %c = icmp slt i8 %x, 0 542 %s = select i1 %c, i8 %n, i8 %x 543 %r = sub i8 0, %s 544 ret i8 %r 545} 546 547define <2 x i8> @negate_nabs(<2 x i8> %x) { 548; CHECK-LABEL: @negate_nabs( 549; CHECK-NEXT: [[N:%.*]] = sub <2 x i8> zeroinitializer, [[X:%.*]] 550; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i8> [[X]], zeroinitializer 551; CHECK-NEXT: [[S:%.*]] = select <2 x i1> [[C]], <2 x i8> [[N]], <2 x i8> [[X]] 552; CHECK-NEXT: ret <2 x i8> [[S]] 553; 554 %n = sub <2 x i8> zeroinitializer, %x 555 %c = icmp slt <2 x i8> %x, zeroinitializer 556 %s = select <2 x i1> %c, <2 x i8> %x, <2 x i8> %n 557 %r = sub <2 x i8> zeroinitializer, %s 558 ret <2 x i8> %r 559} 560 561define i1 @abs_must_be_positive(i32 %x) { 562; CHECK-LABEL: @abs_must_be_positive( 563; CHECK-NEXT: ret i1 true 564; 565 %negx = sub nsw i32 0, %x 566 %c = icmp sge i32 %x, 0 567 %sel = select i1 %c, i32 %x, i32 %negx 568 %c2 = icmp sge i32 %sel, 0 569 ret i1 %c2 570} 571 572