brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.3 KiB · 56a18b0 Raw
394 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s3 4; https://bugs.llvm.org/show_bug.cgi?id=381495 6; We are truncating from wider width, and then sign-extending7; back to the original width. Then we inequality-comparing orig and src.8; If they don't match, then we had signed truncation during truncation.9 10; This can be expressed in a several ways in IR:11;   trunc + sext + icmp ne <- not canonical12;   shl   + ashr + icmp ne13;   add          + icmp ult/ule14;   add          + icmp uge/ugt15; However only the simplest form (with two shifts) gets lowered best.16 17; ---------------------------------------------------------------------------- ;18; shl + ashr + icmp ne19; ---------------------------------------------------------------------------- ;20 21define i1 @shifts_necmp_i16_i8(i16 %x) nounwind {22; CHECK-LABEL: shifts_necmp_i16_i8:23; CHECK:       // %bb.0:24; CHECK-NEXT:    sxtb w8, w025; CHECK-NEXT:    and w8, w8, #0xffff26; CHECK-NEXT:    cmp w8, w0, uxth27; CHECK-NEXT:    cset w0, ne28; CHECK-NEXT:    ret29  %tmp0 = shl i16 %x, 8 ; 16-830  %tmp1 = ashr exact i16 %tmp0, 8 ; 16-831  %tmp2 = icmp ne i16 %tmp1, %x32  ret i1 %tmp233}34 35define i1 @shifts_necmp_i32_i16(i32 %x) nounwind {36; CHECK-LABEL: shifts_necmp_i32_i16:37; CHECK:       // %bb.0:38; CHECK-NEXT:    cmp w0, w0, sxth39; CHECK-NEXT:    cset w0, ne40; CHECK-NEXT:    ret41  %tmp0 = shl i32 %x, 16 ; 32-1642  %tmp1 = ashr exact i32 %tmp0, 16 ; 32-1643  %tmp2 = icmp ne i32 %tmp1, %x44  ret i1 %tmp245}46 47define i1 @shifts_necmp_i32_i8(i32 %x) nounwind {48; CHECK-LABEL: shifts_necmp_i32_i8:49; CHECK:       // %bb.0:50; CHECK-NEXT:    cmp w0, w0, sxtb51; CHECK-NEXT:    cset w0, ne52; CHECK-NEXT:    ret53  %tmp0 = shl i32 %x, 24 ; 32-854  %tmp1 = ashr exact i32 %tmp0, 24 ; 32-855  %tmp2 = icmp ne i32 %tmp1, %x56  ret i1 %tmp257}58 59define i1 @shifts_necmp_i64_i32(i64 %x) nounwind {60; CHECK-LABEL: shifts_necmp_i64_i32:61; CHECK:       // %bb.0:62; CHECK-NEXT:    cmp x0, w0, sxtw63; CHECK-NEXT:    cset w0, ne64; CHECK-NEXT:    ret65  %tmp0 = shl i64 %x, 32 ; 64-3266  %tmp1 = ashr exact i64 %tmp0, 32 ; 64-3267  %tmp2 = icmp ne i64 %tmp1, %x68  ret i1 %tmp269}70 71define i1 @shifts_necmp_i64_i16(i64 %x) nounwind {72; CHECK-LABEL: shifts_necmp_i64_i16:73; CHECK:       // %bb.0:74; CHECK-NEXT:    cmp x0, w0, sxth75; CHECK-NEXT:    cset w0, ne76; CHECK-NEXT:    ret77  %tmp0 = shl i64 %x, 48 ; 64-1678  %tmp1 = ashr exact i64 %tmp0, 48 ; 64-1679  %tmp2 = icmp ne i64 %tmp1, %x80  ret i1 %tmp281}82 83define i1 @shifts_necmp_i64_i8(i64 %x) nounwind {84; CHECK-LABEL: shifts_necmp_i64_i8:85; CHECK:       // %bb.0:86; CHECK-NEXT:    cmp x0, w0, sxtb87; CHECK-NEXT:    cset w0, ne88; CHECK-NEXT:    ret89  %tmp0 = shl i64 %x, 56 ; 64-890  %tmp1 = ashr exact i64 %tmp0, 56 ; 64-891  %tmp2 = icmp ne i64 %tmp1, %x92  ret i1 %tmp293}94 95; ---------------------------------------------------------------------------- ;96; add + icmp ult97; ---------------------------------------------------------------------------- ;98 99define i1 @add_ultcmp_i16_i8(i16 %x) nounwind {100; CHECK-LABEL: add_ultcmp_i16_i8:101; CHECK:       // %bb.0:102; CHECK-NEXT:    and w8, w0, #0xffff103; CHECK-NEXT:    sub w8, w8, #128104; CHECK-NEXT:    lsr w8, w8, #8105; CHECK-NEXT:    cmp w8, #255106; CHECK-NEXT:    cset w0, lo107; CHECK-NEXT:    ret108  %tmp0 = add i16 %x, -128 ; ~0U << (8-1)109  %tmp1 = icmp ult i16 %tmp0, -256 ; ~0U << 8110  ret i1 %tmp1111}112 113define i1 @add_ultcmp_i32_i16(i32 %x) nounwind {114; CHECK-LABEL: add_ultcmp_i32_i16:115; CHECK:       // %bb.0:116; CHECK-NEXT:    cmp w0, w0, sxth117; CHECK-NEXT:    cset w0, ne118; CHECK-NEXT:    ret119  %tmp0 = add i32 %x, -32768 ; ~0U << (16-1)120  %tmp1 = icmp ult i32 %tmp0, -65536 ; ~0U << 16121  ret i1 %tmp1122}123 124define i1 @add_ultcmp_i32_i8(i32 %x) nounwind {125; CHECK-LABEL: add_ultcmp_i32_i8:126; CHECK:       // %bb.0:127; CHECK-NEXT:    cmp w0, w0, sxtb128; CHECK-NEXT:    cset w0, ne129; CHECK-NEXT:    ret130  %tmp0 = add i32 %x, -128 ; ~0U << (8-1)131  %tmp1 = icmp ult i32 %tmp0, -256 ; ~0U << 8132  ret i1 %tmp1133}134 135define i1 @add_ultcmp_i64_i32(i64 %x) nounwind {136; CHECK-LABEL: add_ultcmp_i64_i32:137; CHECK:       // %bb.0:138; CHECK-NEXT:    cmp x0, w0, sxtw139; CHECK-NEXT:    cset w0, ne140; CHECK-NEXT:    ret141  %tmp0 = add i64 %x, -2147483648 ; ~0U << (32-1)142  %tmp1 = icmp ult i64 %tmp0, -4294967296 ; ~0U << 32143  ret i1 %tmp1144}145 146define i1 @add_ultcmp_i64_i16(i64 %x) nounwind {147; CHECK-LABEL: add_ultcmp_i64_i16:148; CHECK:       // %bb.0:149; CHECK-NEXT:    cmp x0, w0, sxth150; CHECK-NEXT:    cset w0, ne151; CHECK-NEXT:    ret152  %tmp0 = add i64 %x, -32768 ; ~0U << (16-1)153  %tmp1 = icmp ult i64 %tmp0, -65536 ; ~0U << 16154  ret i1 %tmp1155}156 157define i1 @add_ultcmp_i64_i8(i64 %x) nounwind {158; CHECK-LABEL: add_ultcmp_i64_i8:159; CHECK:       // %bb.0:160; CHECK-NEXT:    cmp x0, w0, sxtb161; CHECK-NEXT:    cset w0, ne162; CHECK-NEXT:    ret163  %tmp0 = add i64 %x, -128 ; ~0U << (8-1)164  %tmp1 = icmp ult i64 %tmp0, -256 ; ~0U << 8165  ret i1 %tmp1166}167 168; Slightly more canonical variant169define i1 @add_ulecmp_i16_i8(i16 %x) nounwind {170; CHECK-LABEL: add_ulecmp_i16_i8:171; CHECK:       // %bb.0:172; CHECK-NEXT:    and w8, w0, #0xffff173; CHECK-NEXT:    sub w8, w8, #128174; CHECK-NEXT:    lsr w8, w8, #8175; CHECK-NEXT:    cmp w8, #255176; CHECK-NEXT:    cset w0, lo177; CHECK-NEXT:    ret178  %tmp0 = add i16 %x, -128 ; ~0U << (8-1)179  %tmp1 = icmp ule i16 %tmp0, -257 ; ~0U << 8 - 1180  ret i1 %tmp1181}182 183; ---------------------------------------------------------------------------- ;184; add + icmp uge185; ---------------------------------------------------------------------------- ;186 187define i1 @add_ugecmp_i16_i8(i16 %x) nounwind {188; CHECK-LABEL: add_ugecmp_i16_i8:189; CHECK:       // %bb.0:190; CHECK-NEXT:    sxtb w8, w0191; CHECK-NEXT:    and w8, w8, #0xffff192; CHECK-NEXT:    cmp w8, w0, uxth193; CHECK-NEXT:    cset w0, ne194; CHECK-NEXT:    ret195  %tmp0 = add i16 %x, 128 ; 1U << (8-1)196  %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8197  ret i1 %tmp1198}199 200define i1 @add_ugecmp_i32_i16(i32 %x) nounwind {201; CHECK-LABEL: add_ugecmp_i32_i16:202; CHECK:       // %bb.0:203; CHECK-NEXT:    cmp w0, w0, sxth204; CHECK-NEXT:    cset w0, ne205; CHECK-NEXT:    ret206  %tmp0 = add i32 %x, 32768 ; 1U << (16-1)207  %tmp1 = icmp uge i32 %tmp0, 65536 ; 1U << 16208  ret i1 %tmp1209}210 211define i1 @add_ugecmp_i32_i8(i32 %x) nounwind {212; CHECK-LABEL: add_ugecmp_i32_i8:213; CHECK:       // %bb.0:214; CHECK-NEXT:    cmp w0, w0, sxtb215; CHECK-NEXT:    cset w0, ne216; CHECK-NEXT:    ret217  %tmp0 = add i32 %x, 128 ; 1U << (8-1)218  %tmp1 = icmp uge i32 %tmp0, 256 ; 1U << 8219  ret i1 %tmp1220}221 222define i1 @add_ugecmp_i64_i32(i64 %x) nounwind {223; CHECK-LABEL: add_ugecmp_i64_i32:224; CHECK:       // %bb.0:225; CHECK-NEXT:    cmp x0, w0, sxtw226; CHECK-NEXT:    cset w0, ne227; CHECK-NEXT:    ret228  %tmp0 = add i64 %x, 2147483648 ; 1U << (32-1)229  %tmp1 = icmp uge i64 %tmp0, 4294967296 ; 1U << 32230  ret i1 %tmp1231}232 233define i1 @add_ugecmp_i64_i16(i64 %x) nounwind {234; CHECK-LABEL: add_ugecmp_i64_i16:235; CHECK:       // %bb.0:236; CHECK-NEXT:    cmp x0, w0, sxth237; CHECK-NEXT:    cset w0, ne238; CHECK-NEXT:    ret239  %tmp0 = add i64 %x, 32768 ; 1U << (16-1)240  %tmp1 = icmp uge i64 %tmp0, 65536 ; 1U << 16241  ret i1 %tmp1242}243 244define i1 @add_ugecmp_i64_i8(i64 %x) nounwind {245; CHECK-LABEL: add_ugecmp_i64_i8:246; CHECK:       // %bb.0:247; CHECK-NEXT:    cmp x0, w0, sxtb248; CHECK-NEXT:    cset w0, ne249; CHECK-NEXT:    ret250  %tmp0 = add i64 %x, 128 ; 1U << (8-1)251  %tmp1 = icmp uge i64 %tmp0, 256 ; 1U << 8252  ret i1 %tmp1253}254 255; Slightly more canonical variant256define i1 @add_ugtcmp_i16_i8(i16 %x) nounwind {257; CHECK-LABEL: add_ugtcmp_i16_i8:258; CHECK:       // %bb.0:259; CHECK-NEXT:    sxtb w8, w0260; CHECK-NEXT:    and w8, w8, #0xffff261; CHECK-NEXT:    cmp w8, w0, uxth262; CHECK-NEXT:    cset w0, ne263; CHECK-NEXT:    ret264  %tmp0 = add i16 %x, 128 ; 1U << (8-1)265  %tmp1 = icmp ugt i16 %tmp0, 255 ; (1U << 8) - 1266  ret i1 %tmp1267}268 269; Negative tests270; ---------------------------------------------------------------------------- ;271 272; Adding not a constant273define i1 @add_ugecmp_bad_i16_i8_add(i16 %x, i16 %y) nounwind {274; CHECK-LABEL: add_ugecmp_bad_i16_i8_add:275; CHECK:       // %bb.0:276; CHECK-NEXT:    add w8, w0, w1277; CHECK-NEXT:    and w8, w8, #0xffff278; CHECK-NEXT:    cmp w8, #255279; CHECK-NEXT:    cset w0, hi280; CHECK-NEXT:    ret281  %tmp0 = add i16 %x, %y282  %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8283  ret i1 %tmp1284}285 286; Comparing not with a constant287define i1 @add_ugecmp_bad_i16_i8_cmp(i16 %x, i16 %y) nounwind {288; CHECK-LABEL: add_ugecmp_bad_i16_i8_cmp:289; CHECK:       // %bb.0:290; CHECK-NEXT:    add w8, w0, #128291; CHECK-NEXT:    and w8, w8, #0xffff292; CHECK-NEXT:    cmp w8, w1, uxth293; CHECK-NEXT:    cset w0, hs294; CHECK-NEXT:    ret295  %tmp0 = add i16 %x, 128 ; 1U << (8-1)296  %tmp1 = icmp uge i16 %tmp0, %y297  ret i1 %tmp1298}299 300; Second constant is not larger than the first one301define i1 @add_ugecmp_bad_i8_i16(i16 %x) nounwind {302; CHECK-LABEL: add_ugecmp_bad_i8_i16:303; CHECK:       // %bb.0:304; CHECK-NEXT:    add w8, w0, #128305; CHECK-NEXT:    and w8, w8, #0xffff306; CHECK-NEXT:    cmp w8, #127307; CHECK-NEXT:    cset w0, hi308; CHECK-NEXT:    ret309  %tmp0 = add i16 %x, 128 ; 1U << (8-1)310  %tmp1 = icmp uge i16 %tmp0, 128 ; 1U << (8-1)311  ret i1 %tmp1312}313 314; First constant is not power of two315define i1 @add_ugecmp_bad_i16_i8_c0notpoweroftwo(i16 %x) nounwind {316; CHECK-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo:317; CHECK:       // %bb.0:318; CHECK-NEXT:    add w8, w0, #192319; CHECK-NEXT:    and w8, w8, #0xffff320; CHECK-NEXT:    cmp w8, #255321; CHECK-NEXT:    cset w0, hi322; CHECK-NEXT:    ret323  %tmp0 = add i16 %x, 192 ; (1U << (8-1)) + (1U << (8-1-1))324  %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8325  ret i1 %tmp1326}327 328; Second constant is not power of two329define i1 @add_ugecmp_bad_i16_i8_c1notpoweroftwo(i16 %x) nounwind {330; CHECK-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo:331; CHECK:       // %bb.0:332; CHECK-NEXT:    add w8, w0, #128333; CHECK-NEXT:    and w8, w8, #0xffff334; CHECK-NEXT:    cmp w8, #767335; CHECK-NEXT:    cset w0, hi336; CHECK-NEXT:    ret337  %tmp0 = add i16 %x, 128 ; 1U << (8-1)338  %tmp1 = icmp uge i16 %tmp0, 768 ; (1U << 8)) + (1U << (8+1))339  ret i1 %tmp1340}341 342; Magic check fails, 64 << 1 != 256343define i1 @add_ugecmp_bad_i16_i8_magic(i16 %x) nounwind {344; CHECK-LABEL: add_ugecmp_bad_i16_i8_magic:345; CHECK:       // %bb.0:346; CHECK-NEXT:    add w8, w0, #64347; CHECK-NEXT:    and w8, w8, #0xffff348; CHECK-NEXT:    cmp w8, #255349; CHECK-NEXT:    cset w0, hi350; CHECK-NEXT:    ret351  %tmp0 = add i16 %x, 64 ; 1U << (8-1-1)352  %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8353  ret i1 %tmp1354}355 356; Bad 'destination type'357define i1 @add_ugecmp_bad_i16_i4(i16 %x) nounwind {358; CHECK-LABEL: add_ugecmp_bad_i16_i4:359; CHECK:       // %bb.0:360; CHECK-NEXT:    add w8, w0, #8361; CHECK-NEXT:    and w8, w8, #0xffff362; CHECK-NEXT:    cmp w8, #15363; CHECK-NEXT:    cset w0, hi364; CHECK-NEXT:    ret365  %tmp0 = add i16 %x, 8 ; 1U << (4-1)366  %tmp1 = icmp uge i16 %tmp0, 16 ; 1U << 4367  ret i1 %tmp1368}369 370; Bad storage type371define i1 @add_ugecmp_bad_i24_i8(i24 %x) nounwind {372; CHECK-LABEL: add_ugecmp_bad_i24_i8:373; CHECK:       // %bb.0:374; CHECK-NEXT:    add w8, w0, #128375; CHECK-NEXT:    and w8, w8, #0xffffff376; CHECK-NEXT:    cmp w8, #255377; CHECK-NEXT:    cset w0, hi378; CHECK-NEXT:    ret379  %tmp0 = add i24 %x, 128 ; 1U << (8-1)380  %tmp1 = icmp uge i24 %tmp0, 256 ; 1U << 8381  ret i1 %tmp1382}383 384; Slightly more canonical variant385define i1 @add_ugtcmp_bad_i16_i8(i16 %x) nounwind {386; CHECK-LABEL: add_ugtcmp_bad_i16_i8:387; CHECK:       // %bb.0:388; CHECK-NEXT:    mov w0, wzr389; CHECK-NEXT:    ret390  %tmp0 = add i16 %x, 128 ; 1U << (8-1)391  %tmp1 = icmp ugt i16 %tmp0, -1 ; when we +1 it, it will wrap to 0392  ret i1 %tmp1393}394