1577 lines
49 KiB
LLVM
1577 lines
49 KiB
LLVM
|
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||
|
; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefix=X32
|
||
|
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64
|
||
|
|
||
|
;==============================================================================;
|
||
|
; the shift amount is negated (shiftbitwidth - shiftamt)
|
||
|
;==============================================================================;
|
||
|
|
||
|
; shift left
|
||
|
;------------------------------------------------------------------------------;
|
||
|
|
||
|
define i32 @reg32_shl_by_negated(i32 %val, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: reg32_shl_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shll %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_shl_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %esi, %ecx
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shll %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = shl i32 %val, %negshamt
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i32 @load32_shl_by_negated(i32* %valptr, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: load32_shl_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl (%eax), %eax
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shll %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: load32_shl_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %esi, %ecx
|
||
|
; X64-NEXT: movl (%rdi), %eax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shll %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i32, i32* %valptr
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = shl i32 %val, %negshamt
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define void @store32_shl_by_negated(i32 %val, i32* %dstptr, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: store32_shl_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shll %cl, %edx
|
||
|
; X32-NEXT: movl %edx, (%eax)
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: store32_shl_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %edx, %ecx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shll %cl, %edi
|
||
|
; X64-NEXT: movl %edi, (%rsi)
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = shl i32 %val, %negshamt
|
||
|
store i32 %shifted, i32* %dstptr
|
||
|
ret void
|
||
|
}
|
||
|
define void @modify32_shl_by_negated(i32* %valptr, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: modify32_shl_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movb $32, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: shll %cl, (%eax)
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: modify32_shl_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movb $32, %cl
|
||
|
; X64-NEXT: subb %sil, %cl
|
||
|
; X64-NEXT: shll %cl, (%rdi)
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i32, i32* %valptr
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = shl i32 %val, %negshamt
|
||
|
store i32 %shifted, i32* %valptr
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i64 @reg64_shl_by_negated(i64 %val, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: reg64_shl_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %esi, %eax
|
||
|
; X32-NEXT: shll %cl, %eax
|
||
|
; X32-NEXT: shldl %cl, %esi, %edx
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB4_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %eax, %edx
|
||
|
; X32-NEXT: xorl %eax, %eax
|
||
|
; X32-NEXT: .LBB4_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_shl_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rsi, %rcx
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shlq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = shl i64 %val, %negshamt
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
define i64 @load64_shl_by_negated(i64* %valptr, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: load64_shl_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl (%eax), %esi
|
||
|
; X32-NEXT: movl 4(%eax), %edx
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %esi, %eax
|
||
|
; X32-NEXT: shll %cl, %eax
|
||
|
; X32-NEXT: shldl %cl, %esi, %edx
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB5_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %eax, %edx
|
||
|
; X32-NEXT: xorl %eax, %eax
|
||
|
; X32-NEXT: .LBB5_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: load64_shl_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rsi, %rcx
|
||
|
; X64-NEXT: movq (%rdi), %rax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shlq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i64, i64* %valptr
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = shl i64 %val, %negshamt
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
define void @store64_shl_by_negated(i64 %val, i64* %dstptr, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: store64_shl_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %edi
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %edi, %esi
|
||
|
; X32-NEXT: shll %cl, %esi
|
||
|
; X32-NEXT: shldl %cl, %edi, %edx
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB6_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: xorl %esi, %esi
|
||
|
; X32-NEXT: .LBB6_2:
|
||
|
; X32-NEXT: movl %edx, 4(%eax)
|
||
|
; X32-NEXT: movl %esi, (%eax)
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: popl %edi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: store64_shl_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdx, %rcx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shlq %cl, %rdi
|
||
|
; X64-NEXT: movq %rdi, (%rsi)
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = shl i64 %val, %negshamt
|
||
|
store i64 %shifted, i64* %dstptr
|
||
|
ret void
|
||
|
}
|
||
|
define void @modify64_shl_by_negated(i64* %valptr, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: modify64_shl_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %edi
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl (%eax), %edi
|
||
|
; X32-NEXT: movl 4(%eax), %edx
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %edi, %esi
|
||
|
; X32-NEXT: shll %cl, %esi
|
||
|
; X32-NEXT: shldl %cl, %edi, %edx
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB7_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: xorl %esi, %esi
|
||
|
; X32-NEXT: .LBB7_2:
|
||
|
; X32-NEXT: movl %esi, (%eax)
|
||
|
; X32-NEXT: movl %edx, 4(%eax)
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: popl %edi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: modify64_shl_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movb $64, %cl
|
||
|
; X64-NEXT: subb %sil, %cl
|
||
|
; X64-NEXT: shlq %cl, (%rdi)
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i64, i64* %valptr
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = shl i64 %val, %negshamt
|
||
|
store i64 %shifted, i64* %valptr
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
; logical shift right
|
||
|
;------------------------------------------------------------------------------;
|
||
|
|
||
|
define i32 @reg32_lshr_by_negated(i32 %val, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %esi, %ecx
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = lshr i32 %val, %negshamt
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i32 @load32_lshr_by_negated(i32* %valptr, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: load32_lshr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl (%eax), %eax
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: load32_lshr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %esi, %ecx
|
||
|
; X64-NEXT: movl (%rdi), %eax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i32, i32* %valptr
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = lshr i32 %val, %negshamt
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define void @store32_lshr_by_negated(i32 %val, i32* %dstptr, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: store32_lshr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: movl %edx, (%eax)
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: store32_lshr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %edx, %ecx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %edi
|
||
|
; X64-NEXT: movl %edi, (%rsi)
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = lshr i32 %val, %negshamt
|
||
|
store i32 %shifted, i32* %dstptr
|
||
|
ret void
|
||
|
}
|
||
|
define void @modify32_lshr_by_negated(i32* %valptr, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: modify32_lshr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movb $32, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: shrl %cl, (%eax)
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: modify32_lshr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movb $32, %cl
|
||
|
; X64-NEXT: subb %sil, %cl
|
||
|
; X64-NEXT: shrl %cl, (%rdi)
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i32, i32* %valptr
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = lshr i32 %val, %negshamt
|
||
|
store i32 %shifted, i32* %valptr
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i64 @reg64_lshr_by_negated(i64 %val, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB12_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB12_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rsi, %rcx
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = lshr i64 %val, %negshamt
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
define i64 @load64_lshr_by_negated(i64* %valptr, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: load64_lshr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: movl (%ecx), %eax
|
||
|
; X32-NEXT: movl 4(%ecx), %esi
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB13_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB13_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: load64_lshr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rsi, %rcx
|
||
|
; X64-NEXT: movq (%rdi), %rax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i64, i64* %valptr
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = lshr i64 %val, %negshamt
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
define void @store64_lshr_by_negated(i64 %val, i64* %dstptr, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: store64_lshr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %edi
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edi
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %edi, %esi
|
||
|
; X32-NEXT: shrl %cl, %esi
|
||
|
; X32-NEXT: shrdl %cl, %edi, %edx
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB14_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: xorl %esi, %esi
|
||
|
; X32-NEXT: .LBB14_2:
|
||
|
; X32-NEXT: movl %esi, 4(%eax)
|
||
|
; X32-NEXT: movl %edx, (%eax)
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: popl %edi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: store64_lshr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdx, %rcx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shrq %cl, %rdi
|
||
|
; X64-NEXT: movq %rdi, (%rsi)
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = lshr i64 %val, %negshamt
|
||
|
store i64 %shifted, i64* %dstptr
|
||
|
ret void
|
||
|
}
|
||
|
define void @modify64_lshr_by_negated(i64* %valptr, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: modify64_lshr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %edi
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl (%eax), %edx
|
||
|
; X32-NEXT: movl 4(%eax), %edi
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %edi, %esi
|
||
|
; X32-NEXT: shrl %cl, %esi
|
||
|
; X32-NEXT: shrdl %cl, %edi, %edx
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB15_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: xorl %esi, %esi
|
||
|
; X32-NEXT: .LBB15_2:
|
||
|
; X32-NEXT: movl %edx, (%eax)
|
||
|
; X32-NEXT: movl %esi, 4(%eax)
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: popl %edi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: modify64_lshr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movb $64, %cl
|
||
|
; X64-NEXT: subb %sil, %cl
|
||
|
; X64-NEXT: shrq %cl, (%rdi)
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i64, i64* %valptr
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = lshr i64 %val, %negshamt
|
||
|
store i64 %shifted, i64* %valptr
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
; arithmetic shift right
|
||
|
;------------------------------------------------------------------------------;
|
||
|
|
||
|
define i32 @reg32_ashr_by_negated(i32 %val, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: reg32_ashr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: sarl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_ashr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %esi, %ecx
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: sarl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = ashr i32 %val, %negshamt
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i32 @load32_ashr_by_negated(i32* %valptr, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: load32_ashr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl (%eax), %eax
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: sarl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: load32_ashr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %esi, %ecx
|
||
|
; X64-NEXT: movl (%rdi), %eax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: sarl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i32, i32* %valptr
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = ashr i32 %val, %negshamt
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define void @store32_ashr_by_negated(i32 %val, i32* %dstptr, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: store32_ashr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: sarl %cl, %edx
|
||
|
; X32-NEXT: movl %edx, (%eax)
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: store32_ashr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %edx, %ecx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: sarl %cl, %edi
|
||
|
; X64-NEXT: movl %edi, (%rsi)
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = ashr i32 %val, %negshamt
|
||
|
store i32 %shifted, i32* %dstptr
|
||
|
ret void
|
||
|
}
|
||
|
define void @modify32_ashr_by_negated(i32* %valptr, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: modify32_ashr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movb $32, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: sarl %cl, (%eax)
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: modify32_ashr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movb $32, %cl
|
||
|
; X64-NEXT: subb %sil, %cl
|
||
|
; X64-NEXT: sarl %cl, (%rdi)
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i32, i32* %valptr
|
||
|
%negshamt = sub i32 32, %shamt
|
||
|
%shifted = ashr i32 %val, %negshamt
|
||
|
store i32 %shifted, i32* %valptr
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define i64 @reg64_ashr_by_negated(i64 %val, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: reg64_ashr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: sarl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB20_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: sarl $31, %esi
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: .LBB20_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_ashr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rsi, %rcx
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: sarq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = ashr i64 %val, %negshamt
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
define i64 @load64_ashr_by_negated(i64* %valptr, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: load64_ashr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: movl (%ecx), %eax
|
||
|
; X32-NEXT: movl 4(%ecx), %esi
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: sarl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB21_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: sarl $31, %esi
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: .LBB21_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: load64_ashr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rsi, %rcx
|
||
|
; X64-NEXT: movq (%rdi), %rax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: sarq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i64, i64* %valptr
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = ashr i64 %val, %negshamt
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
define void @store64_ashr_by_negated(i64 %val, i64* %dstptr, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: store64_ashr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %edi
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edi
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %edi, %esi
|
||
|
; X32-NEXT: sarl %cl, %esi
|
||
|
; X32-NEXT: shrdl %cl, %edi, %edx
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB22_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: sarl $31, %edi
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: movl %edi, %esi
|
||
|
; X32-NEXT: .LBB22_2:
|
||
|
; X32-NEXT: movl %esi, 4(%eax)
|
||
|
; X32-NEXT: movl %edx, (%eax)
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: popl %edi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: store64_ashr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdx, %rcx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: sarq %cl, %rdi
|
||
|
; X64-NEXT: movq %rdi, (%rsi)
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = ashr i64 %val, %negshamt
|
||
|
store i64 %shifted, i64* %dstptr
|
||
|
ret void
|
||
|
}
|
||
|
define void @modify64_ashr_by_negated(i64* %valptr, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: modify64_ashr_by_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %edi
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl (%eax), %edx
|
||
|
; X32-NEXT: movl 4(%eax), %edi
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %edi, %esi
|
||
|
; X32-NEXT: sarl %cl, %esi
|
||
|
; X32-NEXT: shrdl %cl, %edi, %edx
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB23_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: sarl $31, %edi
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: movl %edi, %esi
|
||
|
; X32-NEXT: .LBB23_2:
|
||
|
; X32-NEXT: movl %edx, (%eax)
|
||
|
; X32-NEXT: movl %esi, 4(%eax)
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: popl %edi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: modify64_ashr_by_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movb $64, %cl
|
||
|
; X64-NEXT: subb %sil, %cl
|
||
|
; X64-NEXT: sarq %cl, (%rdi)
|
||
|
; X64-NEXT: retq
|
||
|
%val = load i64, i64* %valptr
|
||
|
%negshamt = sub i64 64, %shamt
|
||
|
%shifted = ashr i64 %val, %negshamt
|
||
|
store i64 %shifted, i64* %valptr
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||;
|
||
|
; next let's only test simple reg pattern, and only lshr.
|
||
|
;||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||;
|
||
|
|
||
|
;==============================================================================;
|
||
|
; subtraction from negated shift amount
|
||
|
|
||
|
define i32 @reg32_lshr_by_sub_from_negated(i32 %val, i32 %a, i32 %b) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_sub_from_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: negb %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_sub_from_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: # kill: def $edx killed $edx def $rdx
|
||
|
; X64-NEXT: # kill: def $esi killed $esi def $rsi
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: leal (%rsi,%rdx), %ecx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i32 32, %a
|
||
|
%negasubb = sub i32 %nega, %b
|
||
|
%shifted = lshr i32 %val, %negasubb
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_sub_from_negated(i64 %val, i64 %a, i64 %b) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_sub_from_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb %dl, %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB25_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB25_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_sub_from_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: leal (%rdx,%rsi), %ecx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i64 64, %a
|
||
|
%negasubb = sub i64 %nega, %b
|
||
|
%shifted = lshr i64 %val, %negasubb
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
;==============================================================================;
|
||
|
; subtraction of negated shift amount
|
||
|
|
||
|
define i32 @reg32_lshr_by_sub_of_negated(i32 %val, i32 %a, i32 %b) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_sub_of_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_sub_of_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: # kill: def $edx killed $edx def $rdx
|
||
|
; X64-NEXT: # kill: def $esi killed $esi def $rsi
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: leal (%rsi,%rdx), %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i32 32, %a
|
||
|
%negasubb = sub i32 %b, %nega
|
||
|
%shifted = lshr i32 %val, %negasubb
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_sub_of_negated(i64 %val, i64 %a, i64 %b) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_sub_of_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: addb $-64, %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB27_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB27_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_sub_of_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: leal (%rdx,%rsi), %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i64 64, %a
|
||
|
%negasubb = sub i64 %b, %nega
|
||
|
%shifted = lshr i64 %val, %negasubb
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
;==============================================================================;
|
||
|
; add to negated shift amount
|
||
|
;
|
||
|
|
||
|
define i32 @reg32_lshr_by_add_to_negated(i32 %val, i32 %a, i32 %b) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_add_to_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_add_to_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %edx, %ecx
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: subl %esi, %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i32 32, %a
|
||
|
%negasubb = add i32 %nega, %b
|
||
|
%shifted = lshr i32 %val, %negasubb
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_add_to_negated(i64 %val, i64 %a, i64 %b) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_add_to_negated:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: addb $64, %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB29_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB29_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_add_to_negated:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdx, %rcx
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: subl %esi, %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i64 64, %a
|
||
|
%negasubb = add i64 %nega, %b
|
||
|
%shifted = lshr i64 %val, %negasubb
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
;==============================================================================;
|
||
|
; subtraction of negated shift amounts
|
||
|
|
||
|
define i32 @reg32_lshr_by_sub_of_negated_amts(i32 %val, i32 %a, i32 %b) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_sub_of_negated_amts:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_sub_of_negated_amts:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %edx, %ecx
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: subl %esi, %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i32 32, %a
|
||
|
%negb = sub i32 32, %b
|
||
|
%negasubnegb = sub i32 %nega, %negb
|
||
|
%shifted = lshr i32 %val, %negasubnegb
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_sub_of_negated_amts(i64 %val, i64 %a, i64 %b) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_sub_of_negated_amts:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB31_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB31_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_sub_of_negated_amts:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdx, %rcx
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: subl %esi, %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i64 64, %a
|
||
|
%negb = sub i64 64, %b
|
||
|
%negasubnegb = sub i64 %nega, %negb
|
||
|
%shifted = lshr i64 %val, %negasubnegb
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
;==============================================================================;
|
||
|
; addition of negated shift amounts
|
||
|
|
||
|
define i32 @reg32_lshr_by_add_of_negated_amts(i32 %val, i32 %a, i32 %b) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_add_of_negated_amts:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: negb %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_add_of_negated_amts:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: # kill: def $edx killed $edx def $rdx
|
||
|
; X64-NEXT: # kill: def $esi killed $esi def $rsi
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: leal (%rsi,%rdx), %ecx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i32 32, %a
|
||
|
%negb = sub i32 32, %b
|
||
|
%negasubnegb = add i32 %nega, %negb
|
||
|
%shifted = lshr i32 %val, %negasubnegb
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_add_of_negated_amts(i64 %val, i64 %a, i64 %b) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_add_of_negated_amts:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: movb $-128, %cl
|
||
|
; X32-NEXT: subb %dl, %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB33_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB33_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_add_of_negated_amts:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: leal (%rdx,%rsi), %ecx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i64 64, %a
|
||
|
%negb = sub i64 64, %b
|
||
|
%negasubnegb = add i64 %nega, %negb
|
||
|
%shifted = lshr i64 %val, %negasubnegb
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
;==============================================================================;
|
||
|
; and patterns with an actual negation+addition
|
||
|
|
||
|
define i32 @reg32_lshr_by_negated_unfolded(i32 %val, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_negated_unfolded:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_negated_unfolded:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %esi, %ecx
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i32 0, %shamt
|
||
|
%negaaddbitwidth = add i32 %negshamt, 32
|
||
|
%shifted = lshr i32 %val, %negaaddbitwidth
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_negated_unfolded(i64 %val, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_negated_unfolded:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB35_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB35_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_negated_unfolded:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rsi, %rcx
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i64 0, %shamt
|
||
|
%negaaddbitwidth = add i64 %negshamt, 64
|
||
|
%shifted = lshr i64 %val, %negaaddbitwidth
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
define i32 @reg32_lshr_by_negated_unfolded_sub_b(i32 %val, i32 %a, i32 %b) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_negated_unfolded_sub_b:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: negb %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_negated_unfolded_sub_b:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: # kill: def $edx killed $edx def $rdx
|
||
|
; X64-NEXT: # kill: def $esi killed $esi def $rsi
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: leal (%rsi,%rdx), %ecx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i32 0, %a
|
||
|
%negaaddbitwidth = add i32 %nega, 32
|
||
|
%negaaddbitwidthsubb = sub i32 %negaaddbitwidth, %b
|
||
|
%shifted = lshr i32 %val, %negaaddbitwidthsubb
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_negated_unfolded_sub_b(i64 %val, i64 %a, i64 %b) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_negated_unfolded_sub_b:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: movb $64, %cl
|
||
|
; X32-NEXT: subb %dl, %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB37_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB37_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_negated_unfolded_sub_b:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: leal (%rdx,%rsi), %ecx
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i64 0, %a
|
||
|
%negaaddbitwidth = add i64 %nega, 64
|
||
|
%negaaddbitwidthsubb = sub i64 %negaaddbitwidth, %b
|
||
|
%shifted = lshr i64 %val, %negaaddbitwidthsubb
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
define i32 @reg32_lshr_by_b_sub_negated_unfolded(i32 %val, i32 %a, i32 %b) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_b_sub_negated_unfolded:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_b_sub_negated_unfolded:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: # kill: def $edx killed $edx def $rdx
|
||
|
; X64-NEXT: # kill: def $esi killed $esi def $rsi
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: leal (%rsi,%rdx), %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i32 0, %a
|
||
|
%negaaddbitwidth = add i32 %nega, 32
|
||
|
%negaaddbitwidthsubb = sub i32 %b, %negaaddbitwidth
|
||
|
%shifted = lshr i32 %val, %negaaddbitwidthsubb
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_b_sub_negated_unfolded(i64 %val, i64 %a, i64 %b) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_b_sub_negated_unfolded:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: addb $-64, %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB39_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB39_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_b_sub_negated_unfolded:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: leal (%rdx,%rsi), %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i64 0, %a
|
||
|
%negaaddbitwidth = add i64 %nega, 64
|
||
|
%negaaddbitwidthsubb = sub i64 %b, %negaaddbitwidth
|
||
|
%shifted = lshr i64 %val, %negaaddbitwidthsubb
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
define i32 @reg32_lshr_by_negated_unfolded_add_b(i32 %val, i32 %a, i32 %b) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_negated_unfolded_add_b:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_negated_unfolded_add_b:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %edx, %ecx
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: subl %esi, %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i32 0, %a
|
||
|
%negaaddbitwidth = add i32 %nega, 32
|
||
|
%negaaddbitwidthaddb = add i32 %negaaddbitwidth, %b
|
||
|
%shifted = lshr i32 %val, %negaaddbitwidthaddb
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_negated_unfolded_add_b(i64 %val, i64 %a, i64 %b) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_negated_unfolded_add_b:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: addb $64, %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB41_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB41_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_negated_unfolded_add_b:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdx, %rcx
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: subl %esi, %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i64 0, %a
|
||
|
%negaaddbitwidth = add i64 %nega, 64
|
||
|
%negaaddbitwidthaddb = add i64 %negaaddbitwidth, %b
|
||
|
%shifted = lshr i64 %val, %negaaddbitwidthaddb
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
;==============================================================================;
|
||
|
; and patterns with an actual negation+mask
|
||
|
|
||
|
define i32 @reg32_lshr_by_masked_negated_unfolded(i32 %val, i32 %shamt) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_masked_negated_unfolded:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subb {{[0-9]+}}(%esp), %cl
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_masked_negated_unfolded:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %esi, %ecx
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i32 0, %shamt
|
||
|
%negaaddbitwidth = and i32 %negshamt, 31
|
||
|
%shifted = lshr i32 %val, %negaaddbitwidth
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_masked_negated_unfolded(i64 %val, i64 %shamt) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_masked_negated_unfolded:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: movb {{[0-9]+}}(%esp), %dl
|
||
|
; X32-NEXT: subb %dl, %cl
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB43_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB43_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_masked_negated_unfolded:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rsi, %rcx
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: negb %cl
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%negshamt = sub i64 0, %shamt
|
||
|
%negaaddbitwidth = and i64 %negshamt, 63
|
||
|
%shifted = lshr i64 %val, %negaaddbitwidth
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
define i32 @reg32_lshr_by_masked_negated_unfolded_sub_b(i32 %val, i32 %a, i32 %b) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_masked_negated_unfolded_sub_b:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: andl $31, %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_masked_negated_unfolded_sub_b:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %esi, %ecx
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: negl %ecx
|
||
|
; X64-NEXT: andl $31, %ecx
|
||
|
; X64-NEXT: subl %edx, %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i32 0, %a
|
||
|
%negaaddbitwidth = and i32 %nega, 31
|
||
|
%negaaddbitwidthsubb = sub i32 %negaaddbitwidth, %b
|
||
|
%shifted = lshr i32 %val, %negaaddbitwidthsubb
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_masked_negated_unfolded_sub_b(i64 %val, i64 %a, i64 %b) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_masked_negated_unfolded_sub_b:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: andl $63, %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB45_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB45_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_masked_negated_unfolded_sub_b:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rsi, %rcx
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: negl %ecx
|
||
|
; X64-NEXT: andl $63, %ecx
|
||
|
; X64-NEXT: subl %edx, %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i64 0, %a
|
||
|
%negaaddbitwidth = and i64 %nega, 63
|
||
|
%negaaddbitwidthsubb = sub i64 %negaaddbitwidth, %b
|
||
|
%shifted = lshr i64 %val, %negaaddbitwidthsubb
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
define i32 @reg32_lshr_by_masked_b_sub_negated_unfolded(i32 %val, i32 %a, i32 %b) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_masked_b_sub_negated_unfolded:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: andl $31, %edx
|
||
|
; X32-NEXT: subl %edx, %ecx
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_masked_b_sub_negated_unfolded:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movl %edx, %ecx
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: negl %esi
|
||
|
; X64-NEXT: andl $31, %esi
|
||
|
; X64-NEXT: subl %esi, %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i32 0, %a
|
||
|
%negaaddbitwidth = and i32 %nega, 31
|
||
|
%negaaddbitwidthsubb = sub i32 %b, %negaaddbitwidth
|
||
|
%shifted = lshr i32 %val, %negaaddbitwidthsubb
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_masked_b_sub_negated_unfolded(i64 %val, i64 %a, i64 %b) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_masked_b_sub_negated_unfolded:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %edx
|
||
|
; X32-NEXT: andl $63, %edx
|
||
|
; X32-NEXT: subl %edx, %ecx
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB47_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB47_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_masked_b_sub_negated_unfolded:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdx, %rcx
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: negl %esi
|
||
|
; X64-NEXT: andl $63, %esi
|
||
|
; X64-NEXT: subl %esi, %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $rcx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i64 0, %a
|
||
|
%negaaddbitwidth = and i64 %nega, 63
|
||
|
%negaaddbitwidthsubb = sub i64 %b, %negaaddbitwidth
|
||
|
%shifted = lshr i64 %val, %negaaddbitwidthsubb
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
define i32 @reg32_lshr_by_masked_negated_unfolded_add_b(i32 %val, i32 %a, i32 %b) nounwind {
|
||
|
; X32-LABEL: reg32_lshr_by_masked_negated_unfolded_add_b:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: andl $31, %ecx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X32-NEXT: shrl %cl, %eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg32_lshr_by_masked_negated_unfolded_add_b:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: # kill: def $edx killed $edx def $rdx
|
||
|
; X64-NEXT: # kill: def $esi killed $esi def $rsi
|
||
|
; X64-NEXT: movl %edi, %eax
|
||
|
; X64-NEXT: negl %esi
|
||
|
; X64-NEXT: andl $31, %esi
|
||
|
; X64-NEXT: leal (%rsi,%rdx), %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrl %cl, %eax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i32 0, %a
|
||
|
%negaaddbitwidth = and i32 %nega, 31
|
||
|
%negaaddbitwidthaddb = add i32 %negaaddbitwidth, %b
|
||
|
%shifted = lshr i32 %val, %negaaddbitwidthaddb
|
||
|
ret i32 %shifted
|
||
|
}
|
||
|
define i64 @reg64_lshr_by_masked_negated_unfolded_add_b(i64 %val, i64 %a, i64 %b) nounwind {
|
||
|
; X32-LABEL: reg64_lshr_by_masked_negated_unfolded_add_b:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: pushl %esi
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %esi
|
||
|
; X32-NEXT: xorl %ecx, %ecx
|
||
|
; X32-NEXT: subl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: andl $63, %ecx
|
||
|
; X32-NEXT: addl {{[0-9]+}}(%esp), %ecx
|
||
|
; X32-NEXT: movl %esi, %edx
|
||
|
; X32-NEXT: shrl %cl, %edx
|
||
|
; X32-NEXT: shrdl %cl, %esi, %eax
|
||
|
; X32-NEXT: testb $32, %cl
|
||
|
; X32-NEXT: je .LBB49_2
|
||
|
; X32-NEXT: # %bb.1:
|
||
|
; X32-NEXT: movl %edx, %eax
|
||
|
; X32-NEXT: xorl %edx, %edx
|
||
|
; X32-NEXT: .LBB49_2:
|
||
|
; X32-NEXT: popl %esi
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: reg64_lshr_by_masked_negated_unfolded_add_b:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: negl %esi
|
||
|
; X64-NEXT: andl $63, %esi
|
||
|
; X64-NEXT: leal (%rdx,%rsi), %ecx
|
||
|
; X64-NEXT: # kill: def $cl killed $cl killed $ecx
|
||
|
; X64-NEXT: shrq %cl, %rax
|
||
|
; X64-NEXT: retq
|
||
|
%nega = sub i64 0, %a
|
||
|
%negaaddbitwidth = and i64 %nega, 63
|
||
|
%negaaddbitwidthaddb = add i64 %negaaddbitwidth, %b
|
||
|
%shifted = lshr i64 %val, %negaaddbitwidthaddb
|
||
|
ret i64 %shifted
|
||
|
}
|
||
|
|
||
|
define i16 @sh_trunc_sh(i64 %x) {
|
||
|
; X32-LABEL: sh_trunc_sh:
|
||
|
; X32: # %bb.0:
|
||
|
; X32-NEXT: movl {{[0-9]+}}(%esp), %eax
|
||
|
; X32-NEXT: shrl $4, %eax
|
||
|
; X32-NEXT: andl $15, %eax
|
||
|
; X32-NEXT: # kill: def $ax killed $ax killed $eax
|
||
|
; X32-NEXT: retl
|
||
|
;
|
||
|
; X64-LABEL: sh_trunc_sh:
|
||
|
; X64: # %bb.0:
|
||
|
; X64-NEXT: movq %rdi, %rax
|
||
|
; X64-NEXT: shrq $36, %rax
|
||
|
; X64-NEXT: andl $15, %eax
|
||
|
; X64-NEXT: # kill: def $ax killed $ax killed $rax
|
||
|
; X64-NEXT: retq
|
||
|
%s = lshr i64 %x, 24
|
||
|
%t = trunc i64 %s to i16
|
||
|
%r = lshr i16 %t, 12
|
||
|
ret i16 %r
|
||
|
}
|