Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[NFC][X86][AArch64] Add tests for the 'check for [no] signed truncati…
…on' pattern Summary: [[ https://bugs.llvm.org/show_bug.cgi?id=38149 | PR38149 ]] As discussed in https://reviews.llvm.org/D49179#1158957 and later, the IR can be improved: https://rise4fun.com/Alive/gBf ^ that pattern will be produced by Implicit Integer Truncation sanitizer, https://reviews.llvm.org/D48958 https://bugs.llvm.org/show_bug.cgi?id=21530 in signed case, therefore it is probably a good idea to improve it. But as it looks from these tests, i think we want to revert at least some cases in DAGCombine. Reviewers: spatel, craig.topper, RKSimon, javed.absar Reviewed By: spatel Subscribers: kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D49247 llvm-svn: 336917
- Loading branch information
Showing
4 changed files
with
1,372 additions
and
0 deletions.
There are no files selected for viewing
258 changes: 258 additions & 0 deletions
258
llvm/test/CodeGen/AArch64/lack-of-signed-truncation-check.ll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py | ||
; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s | ||
|
||
; https://bugs.llvm.org/show_bug.cgi?id=38149 | ||
|
||
; We are truncating from wider width, and then sign-extending | ||
; back to the original width. Then we inequality-comparing orig and src. | ||
; If they don't match, then we had signed truncation during truncation. | ||
|
||
; This can be expressed in a several ways in IR: | ||
; trunc + sext + icmp ne <- not canonical | ||
; shl + ashr + icmp ne | ||
; add + icmp ult | ||
; add + icmp uge | ||
; However only the simplest form (with two shifts) gets lowered best. | ||
|
||
; ---------------------------------------------------------------------------- ; | ||
; shl + ashr + icmp ne | ||
; ---------------------------------------------------------------------------- ; | ||
|
||
define i1 @shifts_necmp_i16_i8(i16 %x) nounwind { | ||
; CHECK-LABEL: shifts_necmp_i16_i8: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: sxtb w8, w0 | ||
; CHECK-NEXT: and w8, w8, #0xffff | ||
; CHECK-NEXT: cmp w8, w0, uxth | ||
; CHECK-NEXT: cset w0, ne | ||
; CHECK-NEXT: ret | ||
%tmp0 = shl i16 %x, 8 ; 16-8 | ||
%tmp1 = ashr exact i16 %tmp0, 8 ; 16-8 | ||
%tmp2 = icmp ne i16 %tmp1, %x | ||
ret i1 %tmp2 | ||
} | ||
|
||
define i1 @shifts_necmp_i32_i16(i32 %x) nounwind { | ||
; CHECK-LABEL: shifts_necmp_i32_i16: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: sxth w8, w0 | ||
; CHECK-NEXT: cmp w8, w0 | ||
; CHECK-NEXT: cset w0, ne | ||
; CHECK-NEXT: ret | ||
%tmp0 = shl i32 %x, 16 ; 32-16 | ||
%tmp1 = ashr exact i32 %tmp0, 16 ; 32-16 | ||
%tmp2 = icmp ne i32 %tmp1, %x | ||
ret i1 %tmp2 | ||
} | ||
|
||
define i1 @shifts_necmp_i32_i8(i32 %x) nounwind { | ||
; CHECK-LABEL: shifts_necmp_i32_i8: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: sxtb w8, w0 | ||
; CHECK-NEXT: cmp w8, w0 | ||
; CHECK-NEXT: cset w0, ne | ||
; CHECK-NEXT: ret | ||
%tmp0 = shl i32 %x, 24 ; 32-8 | ||
%tmp1 = ashr exact i32 %tmp0, 24 ; 32-8 | ||
%tmp2 = icmp ne i32 %tmp1, %x | ||
ret i1 %tmp2 | ||
} | ||
|
||
define i1 @shifts_necmp_i64_i32(i64 %x) nounwind { | ||
; CHECK-LABEL: shifts_necmp_i64_i32: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: sxtw x8, w0 | ||
; CHECK-NEXT: cmp x8, x0 | ||
; CHECK-NEXT: cset w0, ne | ||
; CHECK-NEXT: ret | ||
%tmp0 = shl i64 %x, 32 ; 64-32 | ||
%tmp1 = ashr exact i64 %tmp0, 32 ; 64-32 | ||
%tmp2 = icmp ne i64 %tmp1, %x | ||
ret i1 %tmp2 | ||
} | ||
|
||
define i1 @shifts_necmp_i64_i16(i64 %x) nounwind { | ||
; CHECK-LABEL: shifts_necmp_i64_i16: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: sxth x8, w0 | ||
; CHECK-NEXT: cmp x8, x0 | ||
; CHECK-NEXT: cset w0, ne | ||
; CHECK-NEXT: ret | ||
%tmp0 = shl i64 %x, 48 ; 64-16 | ||
%tmp1 = ashr exact i64 %tmp0, 48 ; 64-16 | ||
%tmp2 = icmp ne i64 %tmp1, %x | ||
ret i1 %tmp2 | ||
} | ||
|
||
define i1 @shifts_necmp_i64_i8(i64 %x) nounwind { | ||
; CHECK-LABEL: shifts_necmp_i64_i8: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: sxtb x8, w0 | ||
; CHECK-NEXT: cmp x8, x0 | ||
; CHECK-NEXT: cset w0, ne | ||
; CHECK-NEXT: ret | ||
%tmp0 = shl i64 %x, 56 ; 64-8 | ||
%tmp1 = ashr exact i64 %tmp0, 56 ; 64-8 | ||
%tmp2 = icmp ne i64 %tmp1, %x | ||
ret i1 %tmp2 | ||
} | ||
|
||
; ---------------------------------------------------------------------------- ; | ||
; add + icmp ult | ||
; ---------------------------------------------------------------------------- ; | ||
|
||
define i1 @add_ultcmp_i16_i8(i16 %x) nounwind { | ||
; CHECK-LABEL: add_ultcmp_i16_i8: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: sub w8, w0, #128 // =128 | ||
; CHECK-NEXT: ubfx w8, w8, #8, #8 | ||
; CHECK-NEXT: cmp w8, #255 // =255 | ||
; CHECK-NEXT: cset w0, lo | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i16 %x, -128 ; ~0U << (8-1) | ||
%tmp1 = icmp ult i16 %tmp0, -256 ; ~0U << 8 | ||
ret i1 %tmp1 | ||
} | ||
|
||
define i1 @add_ultcmp_i32_i16(i32 %x) nounwind { | ||
; CHECK-LABEL: add_ultcmp_i32_i16: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: sub w8, w0, #8, lsl #12 // =32768 | ||
; CHECK-NEXT: cmn w8, #16, lsl #12 // =65536 | ||
; CHECK-NEXT: cset w0, lo | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i32 %x, -32768 ; ~0U << (16-1) | ||
%tmp1 = icmp ult i32 %tmp0, -65536 ; ~0U << 16 | ||
ret i1 %tmp1 | ||
} | ||
|
||
define i1 @add_ultcmp_i32_i8(i32 %x) nounwind { | ||
; CHECK-LABEL: add_ultcmp_i32_i8: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: sub w8, w0, #128 // =128 | ||
; CHECK-NEXT: cmn w8, #256 // =256 | ||
; CHECK-NEXT: cset w0, lo | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i32 %x, -128 ; ~0U << (8-1) | ||
%tmp1 = icmp ult i32 %tmp0, -256 ; ~0U << 8 | ||
ret i1 %tmp1 | ||
} | ||
|
||
define i1 @add_ultcmp_i64_i32(i64 %x) nounwind { | ||
; CHECK-LABEL: add_ultcmp_i64_i32: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: mov x8, #-2147483648 | ||
; CHECK-NEXT: add x8, x0, x8 | ||
; CHECK-NEXT: mov x9, #-4294967296 | ||
; CHECK-NEXT: cmp x8, x9 | ||
; CHECK-NEXT: cset w0, lo | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i64 %x, -2147483648 ; ~0U << (32-1) | ||
%tmp1 = icmp ult i64 %tmp0, -4294967296 ; ~0U << 32 | ||
ret i1 %tmp1 | ||
} | ||
|
||
define i1 @add_ultcmp_i64_i16(i64 %x) nounwind { | ||
; CHECK-LABEL: add_ultcmp_i64_i16: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: sub x8, x0, #8, lsl #12 // =32768 | ||
; CHECK-NEXT: cmn x8, #16, lsl #12 // =65536 | ||
; CHECK-NEXT: cset w0, lo | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i64 %x, -32768 ; ~0U << (16-1) | ||
%tmp1 = icmp ult i64 %tmp0, -65536 ; ~0U << 16 | ||
ret i1 %tmp1 | ||
} | ||
|
||
define i1 @add_ultcmp_i64_i8(i64 %x) nounwind { | ||
; CHECK-LABEL: add_ultcmp_i64_i8: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: sub x8, x0, #128 // =128 | ||
; CHECK-NEXT: cmn x8, #256 // =256 | ||
; CHECK-NEXT: cset w0, lo | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i64 %x, -128 ; ~0U << (8-1) | ||
%tmp1 = icmp ult i64 %tmp0, -256 ; ~0U << 8 | ||
ret i1 %tmp1 | ||
} | ||
|
||
; ---------------------------------------------------------------------------- ; | ||
; add + icmp uge | ||
; ---------------------------------------------------------------------------- ; | ||
|
||
define i1 @add_ugecmp_i16_i8(i16 %x) nounwind { | ||
; CHECK-LABEL: add_ugecmp_i16_i8: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: add w8, w0, #128 // =128 | ||
; CHECK-NEXT: and w8, w8, #0xffff | ||
; CHECK-NEXT: cmp w8, #255 // =255 | ||
; CHECK-NEXT: cset w0, hi | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i16 %x, 128 ; 1U << (8-1) | ||
%tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8 | ||
ret i1 %tmp1 | ||
} | ||
|
||
define i1 @add_ugecmp_i32_i16(i32 %x) nounwind { | ||
; CHECK-LABEL: add_ugecmp_i32_i16: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: add w8, w0, #8, lsl #12 // =32768 | ||
; CHECK-NEXT: lsr w8, w8, #16 | ||
; CHECK-NEXT: cmp w8, #0 // =0 | ||
; CHECK-NEXT: cset w0, ne | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i32 %x, 32768 ; 1U << (16-1) | ||
%tmp1 = icmp uge i32 %tmp0, 65536 ; 1U << 16 | ||
ret i1 %tmp1 | ||
} | ||
|
||
define i1 @add_ugecmp_i32_i8(i32 %x) nounwind { | ||
; CHECK-LABEL: add_ugecmp_i32_i8: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: add w8, w0, #128 // =128 | ||
; CHECK-NEXT: cmp w8, #255 // =255 | ||
; CHECK-NEXT: cset w0, hi | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i32 %x, 128 ; 1U << (8-1) | ||
%tmp1 = icmp uge i32 %tmp0, 256 ; 1U << 8 | ||
ret i1 %tmp1 | ||
} | ||
|
||
define i1 @add_ugecmp_i64_i32(i64 %x) nounwind { | ||
; CHECK-LABEL: add_ugecmp_i64_i32: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: orr w8, wzr, #0x80000000 | ||
; CHECK-NEXT: add x8, x0, x8 | ||
; CHECK-NEXT: lsr x8, x8, #32 | ||
; CHECK-NEXT: cmp x8, #0 // =0 | ||
; CHECK-NEXT: cset w0, ne | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i64 %x, 2147483648 ; 1U << (32-1) | ||
%tmp1 = icmp uge i64 %tmp0, 4294967296 ; 1U << 32 | ||
ret i1 %tmp1 | ||
} | ||
|
||
define i1 @add_ugecmp_i64_i16(i64 %x) nounwind { | ||
; CHECK-LABEL: add_ugecmp_i64_i16: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: add x8, x0, #8, lsl #12 // =32768 | ||
; CHECK-NEXT: lsr x8, x8, #16 | ||
; CHECK-NEXT: cmp x8, #0 // =0 | ||
; CHECK-NEXT: cset w0, ne | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i64 %x, 32768 ; 1U << (16-1) | ||
%tmp1 = icmp uge i64 %tmp0, 65536 ; 1U << 16 | ||
ret i1 %tmp1 | ||
} | ||
|
||
define i1 @add_ugecmp_i64_i8(i64 %x) nounwind { | ||
; CHECK-LABEL: add_ugecmp_i64_i8: | ||
; CHECK: // %bb.0: | ||
; CHECK-NEXT: add x8, x0, #128 // =128 | ||
; CHECK-NEXT: cmp x8, #255 // =255 | ||
; CHECK-NEXT: cset w0, hi | ||
; CHECK-NEXT: ret | ||
%tmp0 = add i64 %x, 128 ; 1U << (8-1) | ||
%tmp1 = icmp uge i64 %tmp0, 256 ; 1U << 8 | ||
ret i1 %tmp1 | ||
} |
Oops, something went wrong.