From: Roman Lebedev Date: Fri, 13 Jul 2018 16:14:37 +0000 (+0000) Subject: [NFC][X86][AArch64] Negative tests for 'check for [no] signed truncation' pattern X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a97ad691465db8d768623c63e597bedaedb25619;p=llvm [NFC][X86][AArch64] Negative tests for 'check for [no] signed truncation' pattern See D49247, D49266 I'm only adding the sane negative tests, and not adding the one-use tests yet. Also, not adding negative tests for the second pattern with inverted operands yet, since it's handling will be added in later differential. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337014 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/CodeGen/AArch64/lack-of-signed-truncation-check.ll b/test/CodeGen/AArch64/lack-of-signed-truncation-check.ll index e8c6f8459c5..4e2e789d23a 100644 --- a/test/CodeGen/AArch64/lack-of-signed-truncation-check.ll +++ b/test/CodeGen/AArch64/lack-of-signed-truncation-check.ll @@ -256,3 +256,118 @@ define i1 @add_ugecmp_i64_i8(i64 %x) nounwind { %tmp1 = icmp uge i64 %tmp0, 256 ; 1U << 8 ret i1 %tmp1 } + +; Negative tests +; ---------------------------------------------------------------------------- ; + +; Adding not a constant +define i1 @add_ugecmp_bad_i16_i8_add(i16 %x, i16 %y) nounwind { +; CHECK-LABEL: add_ugecmp_bad_i16_i8_add: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, w1 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, #255 // =255 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %tmp0 = add i16 %x, %y + %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Comparing not with a constant +define i1 @add_ugecmp_bad_i16_i8_cmp(i16 %x, i16 %y) nounwind { +; CHECK-LABEL: add_ugecmp_bad_i16_i8_cmp: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #128 // =128 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, w1, uxth +; CHECK-NEXT: cset w0, hs +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp uge i16 %tmp0, %y + ret i1 %tmp1 +} + +; Second constant is not larger than the first one +define i1 @add_ugecmp_bad_i8_i16(i16 %x) nounwind { +; CHECK-LABEL: add_ugecmp_bad_i8_i16: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #128 // =128 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, #127 // =127 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp uge i16 %tmp0, 128 ; 1U << (8-1) + ret i1 %tmp1 +} + +; First constant is not power of two +define i1 @add_ugecmp_bad_i16_i8_c0notpoweroftwo(i16 %x) nounwind { +; CHECK-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #192 // =192 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, #255 // =255 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 192 ; (1U << (8-1)) + (1U << (8-1-1)) + %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Second constant is not power of two +define i1 @add_ugecmp_bad_i16_i8_c1notpoweroftwo(i16 %x) nounwind { +; CHECK-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #128 // =128 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, #767 // =767 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp uge i16 %tmp0, 768 ; (1U << 8)) + (1U << (8+1)) + ret i1 %tmp1 +} + +; Magic check fails, 64 << 1 != 256 +define i1 @add_ugecmp_bad_i16_i8_magic(i16 %x) nounwind { +; CHECK-LABEL: add_ugecmp_bad_i16_i8_magic: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #64 // =64 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, #255 // =255 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 64 ; 1U << (8-1-1) + %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Bad 'destination type' +define i1 @add_ugecmp_bad_i16_i4(i16 %x) nounwind { +; CHECK-LABEL: add_ugecmp_bad_i16_i4: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #8 // =8 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, #15 // =15 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 8 ; 1U << (4-1) + %tmp1 = icmp uge i16 %tmp0, 16 ; 1U << 4 + ret i1 %tmp1 +} + +; Bad storage type +define i1 @add_ugecmp_bad_i24_i8(i24 %x) nounwind { +; CHECK-LABEL: add_ugecmp_bad_i24_i8: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #128 // =128 +; CHECK-NEXT: and w8, w8, #0xffffff +; CHECK-NEXT: cmp w8, #255 // =255 +; CHECK-NEXT: cset w0, hi +; CHECK-NEXT: ret + %tmp0 = add i24 %x, 128 ; 1U << (8-1) + %tmp1 = icmp uge i24 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} diff --git a/test/CodeGen/AArch64/signed-truncation-check.ll b/test/CodeGen/AArch64/signed-truncation-check.ll index ef0d6b068f2..1c26d1ae840 100644 --- a/test/CodeGen/AArch64/signed-truncation-check.ll +++ b/test/CodeGen/AArch64/signed-truncation-check.ll @@ -256,3 +256,117 @@ define i1 @add_ultcmp_i64_i8(i64 %x) nounwind { %tmp1 = icmp ult i64 %tmp0, 256 ; 1U << 8 ret i1 %tmp1 } + +; Negative tests +; ---------------------------------------------------------------------------- ; + +; Adding not a constant +define i1 @add_ultcmp_bad_i16_i8_add(i16 %x, i16 %y) nounwind { +; CHECK-LABEL: add_ultcmp_bad_i16_i8_add: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, w1 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, #256 // =256 +; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: ret + %tmp0 = add i16 %x, %y + %tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Comparing not with a constant +define i1 @add_ultcmp_bad_i16_i8_cmp(i16 %x, i16 %y) nounwind { +; CHECK-LABEL: add_ultcmp_bad_i16_i8_cmp: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #128 // =128 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, w1, uxth +; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp ult i16 %tmp0, %y + ret i1 %tmp1 +} + +; Second constant is not larger than the first one +define i1 @add_ultcmp_bad_i8_i16(i16 %x) nounwind { +; CHECK-LABEL: add_ultcmp_bad_i8_i16: +; CHECK: // %bb.0: +; CHECK-NEXT: and w8, w0, #0xffff +; CHECK-NEXT: add w8, w8, #128 // =128 +; CHECK-NEXT: lsr w0, w8, #16 +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp ult i16 %tmp0, 128 ; 1U << (8-1) + ret i1 %tmp1 +} + +; First constant is not power of two +define i1 @add_ultcmp_bad_i16_i8_c0notpoweroftwo(i16 %x) nounwind { +; CHECK-LABEL: add_ultcmp_bad_i16_i8_c0notpoweroftwo: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #192 // =192 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, #256 // =256 +; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 192 ; (1U << (8-1)) + (1U << (8-1-1)) + %tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Second constant is not power of two +define i1 @add_ultcmp_bad_i16_i8_c1notpoweroftwo(i16 %x) nounwind { +; CHECK-LABEL: add_ultcmp_bad_i16_i8_c1notpoweroftwo: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #128 // =128 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, #768 // =768 +; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp ult i16 %tmp0, 768 ; (1U << 8)) + (1U << (8+1)) + ret i1 %tmp1 +} + +; Magic check fails, 64 << 1 != 256 +define i1 @add_ultcmp_bad_i16_i8_magic(i16 %x) nounwind { +; CHECK-LABEL: add_ultcmp_bad_i16_i8_magic: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #64 // =64 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, #256 // =256 +; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 64 ; 1U << (8-1-1) + %tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Bad 'destination type' +define i1 @add_ultcmp_bad_i16_i4(i16 %x) nounwind { +; CHECK-LABEL: add_ultcmp_bad_i16_i4: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #8 // =8 +; CHECK-NEXT: and w8, w8, #0xffff +; CHECK-NEXT: cmp w8, #16 // =16 +; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: ret + %tmp0 = add i16 %x, 8 ; 1U << (4-1) + %tmp1 = icmp ult i16 %tmp0, 16 ; 1U << 4 + ret i1 %tmp1 +} + +; Bad storage type +define i1 @add_ultcmp_bad_i24_i8(i24 %x) nounwind { +; CHECK-LABEL: add_ultcmp_bad_i24_i8: +; CHECK: // %bb.0: +; CHECK-NEXT: add w8, w0, #128 // =128 +; CHECK-NEXT: and w8, w8, #0xffffff +; CHECK-NEXT: cmp w8, #256 // =256 +; CHECK-NEXT: cset w0, lo +; CHECK-NEXT: ret + %tmp0 = add i24 %x, 128 ; 1U << (8-1) + %tmp1 = icmp ult i24 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} diff --git a/test/CodeGen/X86/lack-of-signed-truncation-check.ll b/test/CodeGen/X86/lack-of-signed-truncation-check.ll index 7b7b177d6c6..cc876f3fe20 100644 --- a/test/CodeGen/X86/lack-of-signed-truncation-check.ll +++ b/test/CodeGen/X86/lack-of-signed-truncation-check.ll @@ -428,3 +428,188 @@ define i1 @add_ugecmp_i64_i8(i64 %x) nounwind { %tmp1 = icmp uge i64 %tmp0, 256 ; 1U << 8 ret i1 %tmp1 } + +; Negative tests +; ---------------------------------------------------------------------------- ; + +; Adding not a constant +define i1 @add_ugecmp_bad_i16_i8_add(i16 %x, i16 %y) nounwind { +; X86-LABEL: add_ugecmp_bad_i16_i8_add: +; X86: # %bb.0: +; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addw {{[0-9]+}}(%esp), %ax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: cmpl $255, %eax +; X86-NEXT: seta %al +; X86-NEXT: retl +; +; X64-LABEL: add_ugecmp_bad_i16_i8_add: +; X64: # %bb.0: +; X64-NEXT: addl %esi, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: cmpl $255, %eax +; X64-NEXT: seta %al +; X64-NEXT: retq + %tmp0 = add i16 %x, %y + %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Comparing not with a constant +define i1 @add_ugecmp_bad_i16_i8_cmp(i16 %x, i16 %y) nounwind { +; X86-LABEL: add_ugecmp_bad_i16_i8_cmp: +; X86: # %bb.0: +; X86-NEXT: movl $128, %eax +; X86-NEXT: addl {{[0-9]+}}(%esp), %eax +; X86-NEXT: cmpw {{[0-9]+}}(%esp), %ax +; X86-NEXT: setae %al +; X86-NEXT: retl +; +; X64-LABEL: add_ugecmp_bad_i16_i8_cmp: +; X64: # %bb.0: +; X64-NEXT: subl $-128, %edi +; X64-NEXT: cmpw %si, %di +; X64-NEXT: setae %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp uge i16 %tmp0, %y + ret i1 %tmp1 +} + +; Second constant is not larger than the first one +define i1 @add_ugecmp_bad_i8_i16(i16 %x) nounwind { +; X86-LABEL: add_ugecmp_bad_i8_i16: +; X86: # %bb.0: +; X86-NEXT: movl $128, %eax +; X86-NEXT: addl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: cmpl $127, %eax +; X86-NEXT: seta %al +; X86-NEXT: retl +; +; X64-LABEL: add_ugecmp_bad_i8_i16: +; X64: # %bb.0: +; X64-NEXT: subl $-128, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: cmpl $127, %eax +; X64-NEXT: seta %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp uge i16 %tmp0, 128 ; 1U << (8-1) + ret i1 %tmp1 +} + +; First constant is not power of two +define i1 @add_ugecmp_bad_i16_i8_c0notpoweroftwo(i16 %x) nounwind { +; X86-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo: +; X86: # %bb.0: +; X86-NEXT: movl $192, %eax +; X86-NEXT: addl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: cmpl $255, %eax +; X86-NEXT: seta %al +; X86-NEXT: retl +; +; X64-LABEL: add_ugecmp_bad_i16_i8_c0notpoweroftwo: +; X64: # %bb.0: +; X64-NEXT: addl $192, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: cmpl $255, %eax +; X64-NEXT: seta %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 192 ; (1U << (8-1)) + (1U << (8-1-1)) + %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Second constant is not power of two +define i1 @add_ugecmp_bad_i16_i8_c1notpoweroftwo(i16 %x) nounwind { +; X86-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo: +; X86: # %bb.0: +; X86-NEXT: movl $128, %eax +; X86-NEXT: addl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: cmpl $767, %eax # imm = 0x2FF +; X86-NEXT: seta %al +; X86-NEXT: retl +; +; X64-LABEL: add_ugecmp_bad_i16_i8_c1notpoweroftwo: +; X64: # %bb.0: +; X64-NEXT: subl $-128, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: cmpl $767, %eax # imm = 0x2FF +; X64-NEXT: seta %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp uge i16 %tmp0, 768 ; (1U << 8)) + (1U << (8+1)) + ret i1 %tmp1 +} + +; Magic check fails, 64 << 1 != 256 +define i1 @add_ugecmp_bad_i16_i8_magic(i16 %x) nounwind { +; X86-LABEL: add_ugecmp_bad_i16_i8_magic: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl $64, %eax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: cmpl $255, %eax +; X86-NEXT: seta %al +; X86-NEXT: retl +; +; X64-LABEL: add_ugecmp_bad_i16_i8_magic: +; X64: # %bb.0: +; X64-NEXT: addl $64, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: cmpl $255, %eax +; X64-NEXT: seta %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 64 ; 1U << (8-1-1) + %tmp1 = icmp uge i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Bad 'destination type' +define i1 @add_ugecmp_bad_i16_i4(i16 %x) nounwind { +; X86-LABEL: add_ugecmp_bad_i16_i4: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl $8, %eax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: cmpl $15, %eax +; X86-NEXT: seta %al +; X86-NEXT: retl +; +; X64-LABEL: add_ugecmp_bad_i16_i4: +; X64: # %bb.0: +; X64-NEXT: addl $8, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: cmpl $15, %eax +; X64-NEXT: seta %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 8 ; 1U << (4-1) + %tmp1 = icmp uge i16 %tmp0, 16 ; 1U << 4 + ret i1 %tmp1 +} + +; Bad storage type +define i1 @add_ugecmp_bad_i24_i8(i24 %x) nounwind { +; X86-LABEL: add_ugecmp_bad_i24_i8: +; X86: # %bb.0: +; X86-NEXT: movl $128, %eax +; X86-NEXT: addl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $16777215, %eax # imm = 0xFFFFFF +; X86-NEXT: cmpl $255, %eax +; X86-NEXT: seta %al +; X86-NEXT: retl +; +; X64-LABEL: add_ugecmp_bad_i24_i8: +; X64: # %bb.0: +; X64-NEXT: subl $-128, %edi +; X64-NEXT: andl $16777215, %edi # imm = 0xFFFFFF +; X64-NEXT: cmpl $255, %edi +; X64-NEXT: seta %al +; X64-NEXT: retq + %tmp0 = add i24 %x, 128 ; 1U << (8-1) + %tmp1 = icmp uge i24 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} diff --git a/test/CodeGen/X86/signed-truncation-check.ll b/test/CodeGen/X86/signed-truncation-check.ll index c5de30417d3..91cdef2a75b 100644 --- a/test/CodeGen/X86/signed-truncation-check.ll +++ b/test/CodeGen/X86/signed-truncation-check.ll @@ -424,3 +424,184 @@ define i1 @add_ultcmp_i64_i8(i64 %x) nounwind { %tmp1 = icmp ult i64 %tmp0, 256 ; 1U << 8 ret i1 %tmp1 } + +; Negative tests +; ---------------------------------------------------------------------------- ; + +; Adding not a constant +define i1 @add_ultcmp_bad_i16_i8_add(i16 %x, i16 %y) nounwind { +; X86-LABEL: add_ultcmp_bad_i16_i8_add: +; X86: # %bb.0: +; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addw {{[0-9]+}}(%esp), %ax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: cmpl $256, %eax # imm = 0x100 +; X86-NEXT: setb %al +; X86-NEXT: retl +; +; X64-LABEL: add_ultcmp_bad_i16_i8_add: +; X64: # %bb.0: +; X64-NEXT: addl %esi, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: cmpl $256, %eax # imm = 0x100 +; X64-NEXT: setb %al +; X64-NEXT: retq + %tmp0 = add i16 %x, %y + %tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Comparing not with a constant +define i1 @add_ultcmp_bad_i16_i8_cmp(i16 %x, i16 %y) nounwind { +; X86-LABEL: add_ultcmp_bad_i16_i8_cmp: +; X86: # %bb.0: +; X86-NEXT: movl $128, %eax +; X86-NEXT: addl {{[0-9]+}}(%esp), %eax +; X86-NEXT: cmpw {{[0-9]+}}(%esp), %ax +; X86-NEXT: setb %al +; X86-NEXT: retl +; +; X64-LABEL: add_ultcmp_bad_i16_i8_cmp: +; X64: # %bb.0: +; X64-NEXT: subl $-128, %edi +; X64-NEXT: cmpw %si, %di +; X64-NEXT: setb %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp ult i16 %tmp0, %y + ret i1 %tmp1 +} + +; Second constant is not larger than the first one +define i1 @add_ultcmp_bad_i8_i16(i16 %x) nounwind { +; X86-LABEL: add_ultcmp_bad_i8_i16: +; X86: # %bb.0: +; X86-NEXT: movw $128, %ax +; X86-NEXT: addw {{[0-9]+}}(%esp), %ax +; X86-NEXT: setb %al +; X86-NEXT: retl +; +; X64-LABEL: add_ultcmp_bad_i8_i16: +; X64: # %bb.0: +; X64-NEXT: addw $128, %di +; X64-NEXT: setb %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp ult i16 %tmp0, 128 ; 1U << (8-1) + ret i1 %tmp1 +} + +; First constant is not power of two +define i1 @add_ultcmp_bad_i16_i8_c0notpoweroftwo(i16 %x) nounwind { +; X86-LABEL: add_ultcmp_bad_i16_i8_c0notpoweroftwo: +; X86: # %bb.0: +; X86-NEXT: movl $192, %eax +; X86-NEXT: addl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: cmpl $256, %eax # imm = 0x100 +; X86-NEXT: setb %al +; X86-NEXT: retl +; +; X64-LABEL: add_ultcmp_bad_i16_i8_c0notpoweroftwo: +; X64: # %bb.0: +; X64-NEXT: addl $192, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: cmpl $256, %eax # imm = 0x100 +; X64-NEXT: setb %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 192 ; (1U << (8-1)) + (1U << (8-1-1)) + %tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Second constant is not power of two +define i1 @add_ultcmp_bad_i16_i8_c1notpoweroftwo(i16 %x) nounwind { +; X86-LABEL: add_ultcmp_bad_i16_i8_c1notpoweroftwo: +; X86: # %bb.0: +; X86-NEXT: movl $128, %eax +; X86-NEXT: addl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: cmpl $768, %eax # imm = 0x300 +; X86-NEXT: setb %al +; X86-NEXT: retl +; +; X64-LABEL: add_ultcmp_bad_i16_i8_c1notpoweroftwo: +; X64: # %bb.0: +; X64-NEXT: subl $-128, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: cmpl $768, %eax # imm = 0x300 +; X64-NEXT: setb %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 128 ; 1U << (8-1) + %tmp1 = icmp ult i16 %tmp0, 768 ; (1U << 8)) + (1U << (8+1)) + ret i1 %tmp1 +} + +; Magic check fails, 64 << 1 != 256 +define i1 @add_ultcmp_bad_i16_i8_magic(i16 %x) nounwind { +; X86-LABEL: add_ultcmp_bad_i16_i8_magic: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl $64, %eax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: cmpl $256, %eax # imm = 0x100 +; X86-NEXT: setb %al +; X86-NEXT: retl +; +; X64-LABEL: add_ultcmp_bad_i16_i8_magic: +; X64: # %bb.0: +; X64-NEXT: addl $64, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: cmpl $256, %eax # imm = 0x100 +; X64-NEXT: setb %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 64 ; 1U << (8-1-1) + %tmp1 = icmp ult i16 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +} + +; Bad 'destination type' +define i1 @add_ultcmp_bad_i16_i4(i16 %x) nounwind { +; X86-LABEL: add_ultcmp_bad_i16_i4: +; X86: # %bb.0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: addl $8, %eax +; X86-NEXT: movzwl %ax, %eax +; X86-NEXT: cmpl $16, %eax +; X86-NEXT: setb %al +; X86-NEXT: retl +; +; X64-LABEL: add_ultcmp_bad_i16_i4: +; X64: # %bb.0: +; X64-NEXT: addl $8, %edi +; X64-NEXT: movzwl %di, %eax +; X64-NEXT: cmpl $16, %eax +; X64-NEXT: setb %al +; X64-NEXT: retq + %tmp0 = add i16 %x, 8 ; 1U << (4-1) + %tmp1 = icmp ult i16 %tmp0, 16 ; 1U << 4 + ret i1 %tmp1 +} + +; Bad storage type +define i1 @add_ultcmp_bad_i24_i8(i24 %x) nounwind { +; X86-LABEL: add_ultcmp_bad_i24_i8: +; X86: # %bb.0: +; X86-NEXT: movl $128, %eax +; X86-NEXT: addl {{[0-9]+}}(%esp), %eax +; X86-NEXT: andl $16777215, %eax # imm = 0xFFFFFF +; X86-NEXT: cmpl $256, %eax # imm = 0x100 +; X86-NEXT: setb %al +; X86-NEXT: retl +; +; X64-LABEL: add_ultcmp_bad_i24_i8: +; X64: # %bb.0: +; X64-NEXT: subl $-128, %edi +; X64-NEXT: andl $16777215, %edi # imm = 0xFFFFFF +; X64-NEXT: cmpl $256, %edi # imm = 0x100 +; X64-NEXT: setb %al +; X64-NEXT: retq + %tmp0 = add i24 %x, 128 ; 1U << (8-1) + %tmp1 = icmp ult i24 %tmp0, 256 ; 1U << 8 + ret i1 %tmp1 +}