| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 | |
| ; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s --check-prefixes=X64 | |
| ; RUN: llc < %s -mtriple=i686-- | FileCheck %s --check-prefixes=X86 | |
| ; Test for https://github.com/llvm/llvm-project/issues/172674. | |
| define i1 @top_i16_range(i64 %x) nounwind { | |
| ; X64-LABEL: top_i16_range: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: shrq $49, %rdi | |
| ; X64-NEXT: addl $-5, %edi | |
| ; X64-NEXT: cmpl $5, %edi | |
| ; X64-NEXT: setb %al | |
| ; X64-NEXT: retq | |
| ; | |
| ; X86-LABEL: top_i16_range: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: shrl $17, %eax | |
| ; X86-NEXT: xorl %ecx, %ecx | |
| ; X86-NEXT: addl $-5, %eax | |
| ; X86-NEXT: adcl $-1, %ecx | |
| ; X86-NEXT: cmpl $5, %eax | |
| ; X86-NEXT: sbbl $0, %ecx | |
| ; X86-NEXT: setb %al | |
| ; X86-NEXT: retl | |
| %offset = add i64 %x, -2814749767106560 | |
| %in.range = icmp ult i64 %offset, 2814749767106560 | |
| ret i1 %in.range | |
| } | |
| define i1 @top_i32_range(i64 %x) nounwind { | |
| ; X64-LABEL: top_i32_range: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: shrq $32, %rdi | |
| ; X64-NEXT: addq $-123, %rdi | |
| ; X64-NEXT: cmpq $333, %rdi # imm = 0x14D | |
| ; X64-NEXT: setb %al | |
| ; X64-NEXT: retq | |
| ; | |
| ; X86-LABEL: top_i32_range: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: xorl %ecx, %ecx | |
| ; X86-NEXT: addl $-123, %eax | |
| ; X86-NEXT: adcl $-1, %ecx | |
| ; X86-NEXT: cmpl $333, %eax # imm = 0x14D | |
| ; X86-NEXT: sbbl $0, %ecx | |
| ; X86-NEXT: setb %al | |
| ; X86-NEXT: retl | |
| %offset = add i64 %x, -528280977408 | |
| %in.range = icmp ult i64 %offset, 1430224109568 | |
| ret i1 %in.range | |
| } | |
| define i1 @top_i32_range_uge(i64 %x) nounwind { | |
| ; X64-LABEL: top_i32_range_uge: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: shrq $32, %rdi | |
| ; X64-NEXT: addq $-123, %rdi | |
| ; X64-NEXT: cmpq $333, %rdi # imm = 0x14D | |
| ; X64-NEXT: setae %al | |
| ; X64-NEXT: retq | |
| ; | |
| ; X86-LABEL: top_i32_range_uge: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: pushl %esi | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: xorl %ecx, %ecx | |
| ; X86-NEXT: addl $-123, %eax | |
| ; X86-NEXT: movl $0, %edx | |
| ; X86-NEXT: adcl $-1, %edx | |
| ; X86-NEXT: movl $332, %esi # imm = 0x14C | |
| ; X86-NEXT: cmpl %eax, %esi | |
| ; X86-NEXT: sbbl %edx, %ecx | |
| ; X86-NEXT: setb %al | |
| ; X86-NEXT: popl %esi | |
| ; X86-NEXT: retl | |
| %offset = add i64 %x, -528280977408 | |
| %out.range = icmp uge i64 %offset, 1430224109568 | |
| ret i1 %out.range | |
| } | |
| define i1 @top_i16_range_ule(i64 %x) nounwind { | |
| ; X64-LABEL: top_i16_range_ule: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: shrq $49, %rdi | |
| ; X64-NEXT: addl $-5, %edi | |
| ; X64-NEXT: cmpl $5, %edi | |
| ; X64-NEXT: setb %al | |
| ; X64-NEXT: retq | |
| ; | |
| ; X86-LABEL: top_i16_range_ule: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: shrl $17, %eax | |
| ; X86-NEXT: xorl %ecx, %ecx | |
| ; X86-NEXT: addl $-5, %eax | |
| ; X86-NEXT: adcl $-1, %ecx | |
| ; X86-NEXT: cmpl $5, %eax | |
| ; X86-NEXT: sbbl $0, %ecx | |
| ; X86-NEXT: setb %al | |
| ; X86-NEXT: retl | |
| %offset = add i64 %x, -2814749767106560 | |
| %in.range = icmp ule i64 %offset, 2814749767106559 | |
| ret i1 %in.range | |
| } | |
| define i1 @top_i8_range(i64 %x) nounwind { | |
| ; X64-LABEL: top_i8_range: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: shrq $56, %rdi | |
| ; X64-NEXT: addl $-200, %edi | |
| ; X64-NEXT: cmpl $5, %edi | |
| ; X64-NEXT: setb %al | |
| ; X64-NEXT: retq | |
| ; | |
| ; X86-LABEL: top_i8_range: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: xorl %ecx, %ecx | |
| ; X86-NEXT: addl $-200, %eax | |
| ; X86-NEXT: adcl $-1, %ecx | |
| ; X86-NEXT: cmpl $5, %eax | |
| ; X86-NEXT: sbbl $0, %ecx | |
| ; X86-NEXT: setb %al | |
| ; X86-NEXT: retl | |
| %offset = add i64 %x, 4035225266123964416 | |
| %in.range = icmp ult i64 %offset, 360287970189639680 | |
| ret i1 %in.range | |
| } | |
| define i1 @signed_min_add_offset(i64 %x) nounwind { | |
| ; X64-LABEL: signed_min_add_offset: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: shrq $60, %rdi | |
| ; X64-NEXT: addl $-8, %edi | |
| ; X64-NEXT: cmpl $3, %edi | |
| ; X64-NEXT: setb %al | |
| ; X64-NEXT: retq | |
| ; | |
| ; X86-LABEL: signed_min_add_offset: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: shrl $28, %eax | |
| ; X86-NEXT: xorl %ecx, %ecx | |
| ; X86-NEXT: addl $-8, %eax | |
| ; X86-NEXT: adcl $-1, %ecx | |
| ; X86-NEXT: cmpl $3, %eax | |
| ; X86-NEXT: sbbl $0, %ecx | |
| ; X86-NEXT: setb %al | |
| ; X86-NEXT: retl | |
| %offset = add i64 %x, -9223372036854775808 | |
| %in.range = icmp ult i64 %offset, 3458764513820540928 | |
| ret i1 %in.range | |
| } | |
| ; The selected range wraps around the 8-bit boundary, so the offset cannot be | |
| ; moved after the shift without preserving that wrapping behavior. | |
| define i1 @wrapping_range(i64 %x) nounwind { | |
| ; X64-LABEL: wrapping_range: | |
| ; X64: # %bb.0: | |
| ; X64-NEXT: movabsq $432345564227567616, %rax # imm = 0x600000000000000 | |
| ; X64-NEXT: addq %rdi, %rax | |
| ; X64-NEXT: shrq $58, %rax | |
| ; X64-NEXT: cmpl $5, %eax | |
| ; X64-NEXT: setb %al | |
| ; X64-NEXT: retq | |
| ; | |
| ; X86-LABEL: wrapping_range: | |
| ; X86: # %bb.0: | |
| ; X86-NEXT: movl $100663296, %eax # imm = 0x6000000 | |
| ; X86-NEXT: addl {{[0-9]+}}(%esp), %eax | |
| ; X86-NEXT: shrl $26, %eax | |
| ; X86-NEXT: cmpl $5, %eax | |
| ; X86-NEXT: setb %al | |
| ; X86-NEXT: retl | |
| %offset = add i64 %x, 432345564227567616 | |
| %in.range = icmp ult i64 %offset, 1441151880758558720 | |
| ret i1 %in.range | |
| } |