1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=aarch64 | FileCheck %s 3 4; 5; trunc(nabs(sub(zext(a),zext(b)))) -> nabds(a,b) 6; 7 8define i8 @abd_ext_i8(i8 %a, i8 %b) nounwind { 9; CHECK-LABEL: abd_ext_i8: 10; CHECK: // %bb.0: 11; CHECK-NEXT: and w8, w0, #0xff 12; CHECK-NEXT: sub w8, w8, w1, uxtb 13; CHECK-NEXT: cmp w8, #0 14; CHECK-NEXT: cneg w0, w8, pl 15; CHECK-NEXT: ret 16 %aext = zext i8 %a to i64 17 %bext = zext i8 %b to i64 18 %sub = sub i64 %aext, %bext 19 %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false) 20 %nabs = sub i64 0, %abs 21 %trunc = trunc i64 %nabs to i8 22 ret i8 %trunc 23} 24 25define i8 @abd_ext_i8_i16(i8 %a, i16 %b) nounwind { 26; CHECK-LABEL: abd_ext_i8_i16: 27; CHECK: // %bb.0: 28; CHECK-NEXT: and w8, w0, #0xff 29; CHECK-NEXT: sub w8, w8, w1, uxth 30; CHECK-NEXT: cmp w8, #0 31; CHECK-NEXT: cneg w0, w8, pl 32; CHECK-NEXT: ret 33 %aext = zext i8 %a to i64 34 %bext = zext i16 %b to i64 35 %sub = sub i64 %aext, %bext 36 %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false) 37 %nabs = sub i64 0, %abs 38 %trunc = trunc i64 %nabs to i8 39 ret i8 %trunc 40} 41 42define i8 @abd_ext_i8_undef(i8 %a, i8 %b) nounwind { 43; CHECK-LABEL: abd_ext_i8_undef: 44; CHECK: // %bb.0: 45; CHECK-NEXT: and w8, w0, #0xff 46; CHECK-NEXT: sub w8, w8, w1, uxtb 47; CHECK-NEXT: cmp w8, #0 48; CHECK-NEXT: cneg w0, w8, pl 49; CHECK-NEXT: ret 50 %aext = zext i8 %a to i64 51 %bext = zext i8 %b to i64 52 %sub = sub i64 %aext, %bext 53 %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true) 54 %nabs = sub i64 0, %abs 55 %trunc = trunc i64 %nabs to i8 56 ret i8 %trunc 57} 58 59define i16 @abd_ext_i16(i16 %a, i16 %b) nounwind { 60; CHECK-LABEL: abd_ext_i16: 61; CHECK: // %bb.0: 62; CHECK-NEXT: and w8, w0, #0xffff 63; CHECK-NEXT: sub w8, w8, w1, uxth 64; CHECK-NEXT: cmp w8, #0 65; CHECK-NEXT: cneg w0, w8, pl 66; CHECK-NEXT: ret 67 %aext = zext i16 %a to i64 68 %bext = zext i16 %b to i64 69 %sub = sub i64 %aext, %bext 70 %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false) 71 %nabs = sub i64 0, %abs 72 %trunc = trunc i64 %nabs to i16 73 ret i16 %trunc 74} 75 76define i16 @abd_ext_i16_i32(i16 %a, i32 %b) nounwind { 77; CHECK-LABEL: abd_ext_i16_i32: 78; CHECK: // %bb.0: 79; CHECK-NEXT: and w8, w0, #0xffff 80; CHECK-NEXT: sub w9, w1, w8 81; CHECK-NEXT: subs w8, w8, w1 82; CHECK-NEXT: csel w8, w8, w9, hi 83; CHECK-NEXT: neg w0, w8 84; CHECK-NEXT: ret 85 %aext = zext i16 %a to i64 86 %bext = zext i32 %b to i64 87 %sub = sub i64 %aext, %bext 88 %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false) 89 %nabs = sub i64 0, %abs 90 %trunc = trunc i64 %nabs to i16 91 ret i16 %trunc 92} 93 94define i16 @abd_ext_i16_undef(i16 %a, i16 %b) nounwind { 95; CHECK-LABEL: abd_ext_i16_undef: 96; CHECK: // %bb.0: 97; CHECK-NEXT: and w8, w0, #0xffff 98; CHECK-NEXT: sub w8, w8, w1, uxth 99; CHECK-NEXT: cmp w8, #0 100; CHECK-NEXT: cneg w0, w8, pl 101; CHECK-NEXT: ret 102 %aext = zext i16 %a to i64 103 %bext = zext i16 %b to i64 104 %sub = sub i64 %aext, %bext 105 %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true) 106 %nabs = sub i64 0, %abs 107 %trunc = trunc i64 %nabs to i16 108 ret i16 %trunc 109} 110 111define i32 @abd_ext_i32(i32 %a, i32 %b) nounwind { 112; CHECK-LABEL: abd_ext_i32: 113; CHECK: // %bb.0: 114; CHECK-NEXT: sub w8, w1, w0 115; CHECK-NEXT: subs w9, w0, w1 116; CHECK-NEXT: csel w8, w9, w8, hi 117; CHECK-NEXT: neg w0, w8 118; CHECK-NEXT: ret 119 %aext = zext i32 %a to i64 120 %bext = zext i32 %b to i64 121 %sub = sub i64 %aext, %bext 122 %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false) 123 %nabs = sub i64 0, %abs 124 %trunc = trunc i64 %nabs to i32 125 ret i32 %trunc 126} 127 128define i32 @abd_ext_i32_i16(i32 %a, i16 %b) nounwind { 129; CHECK-LABEL: abd_ext_i32_i16: 130; CHECK: // %bb.0: 131; CHECK-NEXT: and w8, w1, #0xffff 132; CHECK-NEXT: sub w9, w8, w0 133; CHECK-NEXT: subs w8, w0, w8 134; CHECK-NEXT: csel w8, w8, w9, hi 135; CHECK-NEXT: neg w0, w8 136; CHECK-NEXT: ret 137 %aext = zext i32 %a to i64 138 %bext = zext i16 %b to i64 139 %sub = sub i64 %aext, %bext 140 %abs = call i64 @llvm.abs.i64(i64 %sub, i1 false) 141 %nabs = sub i64 0, %abs 142 %trunc = trunc i64 %nabs to i32 143 ret i32 %trunc 144} 145 146define i32 @abd_ext_i32_undef(i32 %a, i32 %b) nounwind { 147; CHECK-LABEL: abd_ext_i32_undef: 148; CHECK: // %bb.0: 149; CHECK-NEXT: sub w8, w1, w0 150; CHECK-NEXT: subs w9, w0, w1 151; CHECK-NEXT: csel w8, w9, w8, hi 152; CHECK-NEXT: neg w0, w8 153; CHECK-NEXT: ret 154 %aext = zext i32 %a to i64 155 %bext = zext i32 %b to i64 156 %sub = sub i64 %aext, %bext 157 %abs = call i64 @llvm.abs.i64(i64 %sub, i1 true) 158 %nabs = sub i64 0, %abs 159 %trunc = trunc i64 %nabs to i32 160 ret i32 %trunc 161} 162 163define i64 @abd_ext_i64(i64 %a, i64 %b) nounwind { 164; CHECK-LABEL: abd_ext_i64: 165; CHECK: // %bb.0: 166; CHECK-NEXT: sub x8, x1, x0 167; CHECK-NEXT: subs x9, x0, x1 168; CHECK-NEXT: csel x8, x9, x8, hi 169; CHECK-NEXT: neg x0, x8 170; CHECK-NEXT: ret 171 %aext = zext i64 %a to i128 172 %bext = zext i64 %b to i128 173 %sub = sub i128 %aext, %bext 174 %abs = call i128 @llvm.abs.i128(i128 %sub, i1 false) 175 %nabs = sub i128 0, %abs 176 %trunc = trunc i128 %nabs to i64 177 ret i64 %trunc 178} 179 180define i64 @abd_ext_i64_undef(i64 %a, i64 %b) nounwind { 181; CHECK-LABEL: abd_ext_i64_undef: 182; CHECK: // %bb.0: 183; CHECK-NEXT: sub x8, x1, x0 184; CHECK-NEXT: subs x9, x0, x1 185; CHECK-NEXT: csel x8, x9, x8, hi 186; CHECK-NEXT: neg x0, x8 187; CHECK-NEXT: ret 188 %aext = zext i64 %a to i128 189 %bext = zext i64 %b to i128 190 %sub = sub i128 %aext, %bext 191 %abs = call i128 @llvm.abs.i128(i128 %sub, i1 true) 192 %nabs = sub i128 0, %abs 193 %trunc = trunc i128 %nabs to i64 194 ret i64 %trunc 195} 196 197define i128 @abd_ext_i128(i128 %a, i128 %b) nounwind { 198; CHECK-LABEL: abd_ext_i128: 199; CHECK: // %bb.0: 200; CHECK-NEXT: subs x8, x0, x2 201; CHECK-NEXT: sbcs x9, x1, x3 202; CHECK-NEXT: cset w10, lo 203; CHECK-NEXT: sbfx x10, x10, #0, #1 204; CHECK-NEXT: eor x8, x8, x10 205; CHECK-NEXT: eor x9, x9, x10 206; CHECK-NEXT: subs x8, x8, x10 207; CHECK-NEXT: sbc x9, x9, x10 208; CHECK-NEXT: negs x0, x8 209; CHECK-NEXT: ngc x1, x9 210; CHECK-NEXT: ret 211 %aext = zext i128 %a to i256 212 %bext = zext i128 %b to i256 213 %sub = sub i256 %aext, %bext 214 %abs = call i256 @llvm.abs.i256(i256 %sub, i1 false) 215 %nabs = sub i256 0, %abs 216 %trunc = trunc i256 %nabs to i128 217 ret i128 %trunc 218} 219 220define i128 @abd_ext_i128_undef(i128 %a, i128 %b) nounwind { 221; CHECK-LABEL: abd_ext_i128_undef: 222; CHECK: // %bb.0: 223; CHECK-NEXT: subs x8, x0, x2 224; CHECK-NEXT: sbcs x9, x1, x3 225; CHECK-NEXT: cset w10, lo 226; CHECK-NEXT: sbfx x10, x10, #0, #1 227; CHECK-NEXT: eor x8, x8, x10 228; CHECK-NEXT: eor x9, x9, x10 229; CHECK-NEXT: subs x8, x8, x10 230; CHECK-NEXT: sbc x9, x9, x10 231; CHECK-NEXT: negs x0, x8 232; CHECK-NEXT: ngc x1, x9 233; CHECK-NEXT: ret 234 %aext = zext i128 %a to i256 235 %bext = zext i128 %b to i256 236 %sub = sub i256 %aext, %bext 237 %abs = call i256 @llvm.abs.i256(i256 %sub, i1 true) 238 %nabs = sub i256 0, %abs 239 %trunc = trunc i256 %nabs to i128 240 ret i128 %trunc 241} 242 243; 244; sub(umin(a,b),umax(a,b)) -> nabds(a,b) 245; 246 247define i8 @abd_minmax_i8(i8 %a, i8 %b) nounwind { 248; CHECK-LABEL: abd_minmax_i8: 249; CHECK: // %bb.0: 250; CHECK-NEXT: and w8, w1, #0xff 251; CHECK-NEXT: and w9, w0, #0xff 252; CHECK-NEXT: cmp w9, w8 253; CHECK-NEXT: csel w10, w9, w8, lo 254; CHECK-NEXT: csel w8, w9, w8, hi 255; CHECK-NEXT: sub w0, w10, w8 256; CHECK-NEXT: ret 257 %min = call i8 @llvm.umin.i8(i8 %a, i8 %b) 258 %max = call i8 @llvm.umax.i8(i8 %a, i8 %b) 259 %sub = sub i8 %min, %max 260 ret i8 %sub 261} 262 263define i16 @abd_minmax_i16(i16 %a, i16 %b) nounwind { 264; CHECK-LABEL: abd_minmax_i16: 265; CHECK: // %bb.0: 266; CHECK-NEXT: and w8, w1, #0xffff 267; CHECK-NEXT: and w9, w0, #0xffff 268; CHECK-NEXT: cmp w9, w8 269; CHECK-NEXT: csel w10, w9, w8, lo 270; CHECK-NEXT: csel w8, w9, w8, hi 271; CHECK-NEXT: sub w0, w10, w8 272; CHECK-NEXT: ret 273 %min = call i16 @llvm.umin.i16(i16 %a, i16 %b) 274 %max = call i16 @llvm.umax.i16(i16 %a, i16 %b) 275 %sub = sub i16 %min, %max 276 ret i16 %sub 277} 278 279define i32 @abd_minmax_i32(i32 %a, i32 %b) nounwind { 280; CHECK-LABEL: abd_minmax_i32: 281; CHECK: // %bb.0: 282; CHECK-NEXT: cmp w0, w1 283; CHECK-NEXT: csel w8, w0, w1, lo 284; CHECK-NEXT: csel w9, w0, w1, hi 285; CHECK-NEXT: sub w0, w8, w9 286; CHECK-NEXT: ret 287 %min = call i32 @llvm.umin.i32(i32 %a, i32 %b) 288 %max = call i32 @llvm.umax.i32(i32 %a, i32 %b) 289 %sub = sub i32 %min, %max 290 ret i32 %sub 291} 292 293define i64 @abd_minmax_i64(i64 %a, i64 %b) nounwind { 294; CHECK-LABEL: abd_minmax_i64: 295; CHECK: // %bb.0: 296; CHECK-NEXT: cmp x0, x1 297; CHECK-NEXT: csel x8, x0, x1, lo 298; CHECK-NEXT: csel x9, x0, x1, hi 299; CHECK-NEXT: sub x0, x8, x9 300; CHECK-NEXT: ret 301 %min = call i64 @llvm.umin.i64(i64 %a, i64 %b) 302 %max = call i64 @llvm.umax.i64(i64 %a, i64 %b) 303 %sub = sub i64 %min, %max 304 ret i64 %sub 305} 306 307define i128 @abd_minmax_i128(i128 %a, i128 %b) nounwind { 308; CHECK-LABEL: abd_minmax_i128: 309; CHECK: // %bb.0: 310; CHECK-NEXT: cmp x0, x2 311; CHECK-NEXT: sbcs xzr, x1, x3 312; CHECK-NEXT: csel x8, x1, x3, lo 313; CHECK-NEXT: csel x9, x0, x2, lo 314; CHECK-NEXT: cmp x2, x0 315; CHECK-NEXT: sbcs xzr, x3, x1 316; CHECK-NEXT: csel x10, x0, x2, lo 317; CHECK-NEXT: csel x11, x1, x3, lo 318; CHECK-NEXT: subs x0, x9, x10 319; CHECK-NEXT: sbc x1, x8, x11 320; CHECK-NEXT: ret 321 %min = call i128 @llvm.umin.i128(i128 %a, i128 %b) 322 %max = call i128 @llvm.umax.i128(i128 %a, i128 %b) 323 %sub = sub i128 %min, %max 324 ret i128 %sub 325} 326 327; 328; select(icmp(a,b),sub(a,b),sub(b,a)) -> nabds(a,b) 329; 330 331define i8 @abd_cmp_i8(i8 %a, i8 %b) nounwind { 332; CHECK-LABEL: abd_cmp_i8: 333; CHECK: // %bb.0: 334; CHECK-NEXT: and w8, w0, #0xff 335; CHECK-NEXT: sub w9, w0, w1 336; CHECK-NEXT: sub w10, w1, w0 337; CHECK-NEXT: cmp w8, w1, uxtb 338; CHECK-NEXT: csel w0, w9, w10, ls 339; CHECK-NEXT: ret 340 %cmp = icmp ule i8 %a, %b 341 %ab = sub i8 %a, %b 342 %ba = sub i8 %b, %a 343 %sel = select i1 %cmp, i8 %ab, i8 %ba 344 ret i8 %sel 345} 346 347define i16 @abd_cmp_i16(i16 %a, i16 %b) nounwind { 348; CHECK-LABEL: abd_cmp_i16: 349; CHECK: // %bb.0: 350; CHECK-NEXT: and w8, w0, #0xffff 351; CHECK-NEXT: sub w9, w0, w1 352; CHECK-NEXT: sub w10, w1, w0 353; CHECK-NEXT: cmp w8, w1, uxth 354; CHECK-NEXT: csel w0, w9, w10, lo 355; CHECK-NEXT: ret 356 %cmp = icmp ult i16 %a, %b 357 %ab = sub i16 %a, %b 358 %ba = sub i16 %b, %a 359 %sel = select i1 %cmp, i16 %ab, i16 %ba 360 ret i16 %sel 361} 362 363define i32 @abd_cmp_i32(i32 %a, i32 %b) nounwind { 364; CHECK-LABEL: abd_cmp_i32: 365; CHECK: // %bb.0: 366; CHECK-NEXT: sub w8, w1, w0 367; CHECK-NEXT: subs w9, w0, w1 368; CHECK-NEXT: csel w0, w8, w9, hs 369; CHECK-NEXT: ret 370 %cmp = icmp uge i32 %a, %b 371 %ab = sub i32 %a, %b 372 %ba = sub i32 %b, %a 373 %sel = select i1 %cmp, i32 %ba, i32 %ab 374 ret i32 %sel 375} 376 377define i64 @abd_cmp_i64(i64 %a, i64 %b) nounwind { 378; CHECK-LABEL: abd_cmp_i64: 379; CHECK: // %bb.0: 380; CHECK-NEXT: sub x8, x1, x0 381; CHECK-NEXT: subs x9, x0, x1 382; CHECK-NEXT: csel x0, x9, x8, lo 383; CHECK-NEXT: ret 384 %cmp = icmp ult i64 %a, %b 385 %ab = sub i64 %a, %b 386 %ba = sub i64 %b, %a 387 %sel = select i1 %cmp, i64 %ab, i64 %ba 388 ret i64 %sel 389} 390 391define i128 @abd_cmp_i128(i128 %a, i128 %b) nounwind { 392; CHECK-LABEL: abd_cmp_i128: 393; CHECK: // %bb.0: 394; CHECK-NEXT: cmp x0, x2 395; CHECK-NEXT: sbc x8, x1, x3 396; CHECK-NEXT: subs x9, x2, x0 397; CHECK-NEXT: sbc x10, x3, x1 398; CHECK-NEXT: subs x11, x0, x2 399; CHECK-NEXT: sbcs xzr, x1, x3 400; CHECK-NEXT: csel x0, x11, x9, lo 401; CHECK-NEXT: csel x1, x8, x10, lo 402; CHECK-NEXT: ret 403 %cmp = icmp ult i128 %a, %b 404 %ab = sub i128 %a, %b 405 %ba = sub i128 %b, %a 406 %sel = select i1 %cmp, i128 %ab, i128 %ba 407 ret i128 %sel 408} 409 410declare i8 @llvm.abs.i8(i8, i1) 411declare i16 @llvm.abs.i16(i16, i1) 412declare i32 @llvm.abs.i32(i32, i1) 413declare i64 @llvm.abs.i64(i64, i1) 414declare i128 @llvm.abs.i128(i128, i1) 415 416declare i8 @llvm.umax.i8(i8, i8) 417declare i16 @llvm.umax.i16(i16, i16) 418declare i32 @llvm.umax.i32(i32, i32) 419declare i64 @llvm.umax.i64(i64, i64) 420 421declare i8 @llvm.umin.i8(i8, i8) 422declare i16 @llvm.umin.i16(i16, i16) 423declare i32 @llvm.umin.i32(i32, i32) 424declare i64 @llvm.umin.i64(i64, i64) 425