1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2 ; RUN: opt < %s -instcombine -S | FileCheck %s 3 4 target 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 6 declare i32 @abs(i32) 7 declare i64 @labs(i64) 8 declare i64 @llabs(i64) 9 10 ; Test that the abs library call simplifier works correctly. 11 ; abs(x) -> x <s 0 ? -x : x. 12 13 define 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 24 define 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 35 define 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 48 define 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 63 define <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 78 define <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 93 define 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 106 define 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 119 define 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 134 define 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 149 define <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 165 define 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 178 define 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 195 define 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 212 define 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 227 define <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 242 define <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 257 define 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 270 define 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 283 define 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 298 define 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 313 define <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 328 define 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 341 define 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 358 define 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 377 define 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 390 define 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. 406 define 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 418 define <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 431 define <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 446 define 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 463 declare void @extra_use(i8) 464 465 define 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 483 define 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 496 define 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 509 define <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 521 define 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 533 define 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 547 define <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 561 define 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