Files
clang-p2996/llvm/test/CodeGen/X86/combine-bswap.ll
Sanjay Patel e18cc5277f [SDAG] try to canonicalize logical shift after bswap
When shifting by a byte-multiple:
bswap (shl X, C) --> lshr (bswap X), C
bswap (lshr X, C) --> shl (bswap X), C

This is the backend version of D122010 and an alternative
suggested in D120648.
There's an extra check to make sure the shift amount is
valid that was not in the rough draft.

I'm not sure if there is a larger motivating case for RISCV (bug report?),
but the ARM diffs show a benefit from having a late version of the
transform (because we do not combine the loads in IR).

Differential Revision: https://reviews.llvm.org/D122655
2022-03-30 09:29:32 -04:00

308 lines
8.4 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=i686-unknown -mattr=+sse2 | FileCheck %s --check-prefix=X86
; RUN: llc < %s -mtriple=x86_64-unknown -mattr=+avx | FileCheck %s --check-prefix=X64
; These tests just check that the plumbing is in place for @llvm.bswap. The
; actual output is massive at the moment as llvm.bswap is not yet legal.
declare i16 @llvm.bswap.i16(i16) readnone
declare i32 @llvm.bswap.i32(i32) readnone
declare i64 @llvm.bswap.i64(i64) readnone
declare i32 @llvm.bswap.v4i32(i32) readnone
; fold (bswap undef) -> undef
define i32 @test_undef() nounwind {
; X86-LABEL: test_undef:
; X86: # %bb.0:
; X86-NEXT: retl
;
; X64-LABEL: test_undef:
; X64: # %bb.0:
; X64-NEXT: retq
%b = call i32 @llvm.bswap.i32(i32 undef)
ret i32 %b
}
; fold (bswap (bswap x)) -> x
define i32 @test_bswap_bswap(i32 %a0) nounwind {
; X86-LABEL: test_bswap_bswap:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: retl
;
; X64-LABEL: test_bswap_bswap:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
; X64-NEXT: retq
%b = call i32 @llvm.bswap.i32(i32 %a0)
%c = call i32 @llvm.bswap.i32(i32 %b)
ret i32 %c
}
define i16 @test_bswap_srli_8_bswap_i16(i16 %a) nounwind {
; X86-LABEL: test_bswap_srli_8_bswap_i16:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: shll $8, %eax
; X86-NEXT: # kill: def $ax killed $ax killed $eax
; X86-NEXT: retl
;
; X64-LABEL: test_bswap_srli_8_bswap_i16:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shll $8, %eax
; X64-NEXT: # kill: def $ax killed $ax killed $eax
; X64-NEXT: retq
%1 = call i16 @llvm.bswap.i16(i16 %a)
%2 = lshr i16 %1, 8
%3 = call i16 @llvm.bswap.i16(i16 %2)
ret i16 %3
}
define i32 @test_bswap_srli_8_bswap_i32(i32 %a) nounwind {
; X86-LABEL: test_bswap_srli_8_bswap_i32:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: shll $8, %eax
; X86-NEXT: retl
;
; X64-LABEL: test_bswap_srli_8_bswap_i32:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shll $8, %eax
; X64-NEXT: retq
%1 = call i32 @llvm.bswap.i32(i32 %a)
%2 = lshr i32 %1, 8
%3 = call i32 @llvm.bswap.i32(i32 %2)
ret i32 %3
}
define i64 @test_bswap_srli_16_bswap_i64(i64 %a) nounwind {
; X86-LABEL: test_bswap_srli_16_bswap_i64:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
; X86-NEXT: shll $16, %eax
; X86-NEXT: retl
;
; X64-LABEL: test_bswap_srli_16_bswap_i64:
; X64: # %bb.0:
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: shlq $16, %rax
; X64-NEXT: retq
%1 = call i64 @llvm.bswap.i64(i64 %a)
%2 = lshr i64 %1, 16
%3 = call i64 @llvm.bswap.i64(i64 %2)
ret i64 %3
}
define i16 @test_bswap_shli_8_bswap_i16(i16 %a) nounwind {
; X86-LABEL: test_bswap_shli_8_bswap_i16:
; X86: # %bb.0:
; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax
; X86-NEXT: # kill: def $ax killed $ax killed $eax
; X86-NEXT: retl
;
; X64-LABEL: test_bswap_shli_8_bswap_i16:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
; X64-NEXT: movzbl %ah, %eax
; X64-NEXT: # kill: def $ax killed $ax killed $eax
; X64-NEXT: retq
%1 = call i16 @llvm.bswap.i16(i16 %a)
%2 = shl i16 %1, 8
%3 = call i16 @llvm.bswap.i16(i16 %2)
ret i16 %3
}
define i32 @test_bswap_shli_8_bswap_i32(i32 %a) nounwind {
; X86-LABEL: test_bswap_shli_8_bswap_i32:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: shrl $8, %eax
; X86-NEXT: retl
;
; X64-LABEL: test_bswap_shli_8_bswap_i32:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shrl $8, %eax
; X64-NEXT: retq
%1 = call i32 @llvm.bswap.i32(i32 %a)
%2 = shl i32 %1, 8
%3 = call i32 @llvm.bswap.i32(i32 %2)
ret i32 %3
}
define i64 @test_bswap_shli_16_bswap_i64(i64 %a) nounwind {
; X86-LABEL: test_bswap_shli_16_bswap_i64:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: movzwl {{[0-9]+}}(%esp), %edx
; X86-NEXT: retl
;
; X64-LABEL: test_bswap_shli_16_bswap_i64:
; X64: # %bb.0:
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: shrq $16, %rax
; X64-NEXT: retq
%1 = call i64 @llvm.bswap.i64(i64 %a)
%2 = shl i64 %1, 16
%3 = call i64 @llvm.bswap.i64(i64 %2)
ret i64 %3
}
define i32 @test_demandedbits_bswap(i32 %a0) nounwind {
; X86-LABEL: test_demandedbits_bswap:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: bswapl %eax
; X86-NEXT: andl $-65536, %eax # imm = 0xFFFF0000
; X86-NEXT: retl
;
; X64-LABEL: test_demandedbits_bswap:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
; X64-NEXT: bswapl %eax
; X64-NEXT: andl $-65536, %eax # imm = 0xFFFF0000
; X64-NEXT: retq
%b = or i32 %a0, 4278190080
%c = call i32 @llvm.bswap.i32(i32 %b)
%d = and i32 %c, 4294901760
ret i32 %d
}
define void @demand_one_loaded_byte(i64* %xp, i32* %yp) {
; X86-LABEL: demand_one_loaded_byte:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
; X86-NEXT: movb 4(%ecx), %cl
; X86-NEXT: movb %cl, (%eax)
; X86-NEXT: retl
;
; X64-LABEL: demand_one_loaded_byte:
; X64: # %bb.0:
; X64-NEXT: movb 4(%rdi), %al
; X64-NEXT: movb %al, (%rsi)
; X64-NEXT: retq
%x = load i64, i64* %xp, align 8
%x_zzzz7654 = lshr i64 %x, 32
%x_z7654zzz = shl nuw nsw i64 %x_zzzz7654, 24
%x_4zzz = trunc i64 %x_z7654zzz to i32
%y = load i32, i32* %yp, align 4
%y_321z = and i32 %y, -256
%x_zzz4 = call i32 @llvm.bswap.i32(i32 %x_4zzz)
%r = or i32 %x_zzz4, %y_321z
store i32 %r, i32* %yp, align 4
ret void
}
define i64 @test_bswap64_shift48_zext(i16 %a0) {
; X86-LABEL: test_bswap64_shift48_zext:
; X86: # %bb.0:
; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
; X86-NEXT: rolw $8, %ax
; X86-NEXT: movzwl %ax, %eax
; X86-NEXT: xorl %edx, %edx
; X86-NEXT: retl
;
; X64-LABEL: test_bswap64_shift48_zext:
; X64: # %bb.0:
; X64-NEXT: rolw $8, %di
; X64-NEXT: movzwl %di, %eax
; X64-NEXT: retq
%z = zext i16 %a0 to i64
%s = shl i64 %z, 48
%b = call i64 @llvm.bswap.i64(i64 %s)
ret i64 %b
}
define i64 @test_bswap64_shift48(i64 %a0) {
; X86-LABEL: test_bswap64_shift48:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: rolw $8, %ax
; X86-NEXT: movzwl %ax, %eax
; X86-NEXT: xorl %edx, %edx
; X86-NEXT: retl
;
; X64-LABEL: test_bswap64_shift48:
; X64: # %bb.0:
; X64-NEXT: rolw $8, %di
; X64-NEXT: movzwl %di, %eax
; X64-NEXT: retq
%s = shl i64 %a0, 48
%b = call i64 @llvm.bswap.i64(i64 %s)
ret i64 %b
}
define i32 @test_bswap32_shift17(i32 %a0) {
; X86-LABEL: test_bswap32_shift17:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: shll $17, %eax
; X86-NEXT: bswapl %eax
; X86-NEXT: retl
;
; X64-LABEL: test_bswap32_shift17:
; X64: # %bb.0:
; X64-NEXT: movl %edi, %eax
; X64-NEXT: shll $17, %eax
; X64-NEXT: bswapl %eax
; X64-NEXT: retq
%s = shl i32 %a0, 17
%b = call i32 @llvm.bswap.i32(i32 %s)
ret i32 %b
}
; negative test
define i64 @test_bswap64_shift17(i64 %a0) {
; X86-LABEL: test_bswap64_shift17:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: shldl $17, %edx, %eax
; X86-NEXT: shll $17, %edx
; X86-NEXT: bswapl %eax
; X86-NEXT: bswapl %edx
; X86-NEXT: retl
;
; X64-LABEL: test_bswap64_shift17:
; X64: # %bb.0:
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: shlq $17, %rax
; X64-NEXT: bswapq %rax
; X64-NEXT: retq
%s = shl i64 %a0, 17
%b = call i64 @llvm.bswap.i64(i64 %s)
ret i64 %b
}
; negative test
define i64 @test_bswap64_shift48_multiuse(i64 %a0, i64* %a1) {
; X86-LABEL: test_bswap64_shift48_multiuse:
; X86: # %bb.0:
; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: shll $16, %eax
; X86-NEXT: movl %eax, 4(%ecx)
; X86-NEXT: bswapl %eax
; X86-NEXT: movl %eax, (%ecx)
; X86-NEXT: xorl %edx, %edx
; X86-NEXT: retl
;
; X64-LABEL: test_bswap64_shift48_multiuse:
; X64: # %bb.0:
; X64-NEXT: shlq $48, %rdi
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: bswapq %rax
; X64-NEXT: orq %rax, %rdi
; X64-NEXT: movq %rdi, (%rsi)
; X64-NEXT: retq
%s = shl i64 %a0, 48
%b = call i64 @llvm.bswap.i64(i64 %s)
%a = add i64 %s, %b
store i64 %a, i64* %a1
ret i64 %b
}