| ; 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(ptr %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, ptr %valptr |
| %negshamt = sub i32 32, %shamt |
| %shifted = shl i32 %val, %negshamt |
| ret i32 %shifted |
| } |
| define void @store32_shl_by_negated(i32 %val, ptr %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, ptr %dstptr |
| ret void |
| } |
| define void @modify32_shl_by_negated(ptr %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, ptr %valptr |
| %negshamt = sub i32 32, %shamt |
| %shifted = shl i32 %val, %negshamt |
| store i32 %shifted, ptr %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(ptr %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, ptr %valptr |
| %negshamt = sub i64 64, %shamt |
| %shifted = shl i64 %val, %negshamt |
| ret i64 %shifted |
| } |
| define void @store64_shl_by_negated(i64 %val, ptr %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, ptr %dstptr |
| ret void |
| } |
| define void @modify64_shl_by_negated(ptr %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, ptr %valptr |
| %negshamt = sub i64 64, %shamt |
| %shifted = shl i64 %val, %negshamt |
| store i64 %shifted, ptr %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(ptr %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, ptr %valptr |
| %negshamt = sub i32 32, %shamt |
| %shifted = lshr i32 %val, %negshamt |
| ret i32 %shifted |
| } |
| define void @store32_lshr_by_negated(i32 %val, ptr %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, ptr %dstptr |
| ret void |
| } |
| define void @modify32_lshr_by_negated(ptr %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, ptr %valptr |
| %negshamt = sub i32 32, %shamt |
| %shifted = lshr i32 %val, %negshamt |
| store i32 %shifted, ptr %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(ptr %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, ptr %valptr |
| %negshamt = sub i64 64, %shamt |
| %shifted = lshr i64 %val, %negshamt |
| ret i64 %shifted |
| } |
| define void @store64_lshr_by_negated(i64 %val, ptr %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, ptr %dstptr |
| ret void |
| } |
| define void @modify64_lshr_by_negated(ptr %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, ptr %valptr |
| %negshamt = sub i64 64, %shamt |
| %shifted = lshr i64 %val, %negshamt |
| store i64 %shifted, ptr %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(ptr %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, ptr %valptr |
| %negshamt = sub i32 32, %shamt |
| %shifted = ashr i32 %val, %negshamt |
| ret i32 %shifted |
| } |
| define void @store32_ashr_by_negated(i32 %val, ptr %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, ptr %dstptr |
| ret void |
| } |
| define void @modify32_ashr_by_negated(ptr %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, ptr %valptr |
| %negshamt = sub i32 32, %shamt |
| %shifted = ashr i32 %val, %negshamt |
| store i32 %shifted, ptr %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(ptr %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, ptr %valptr |
| %negshamt = sub i64 64, %shamt |
| %shifted = ashr i64 %val, %negshamt |
| ret i64 %shifted |
| } |
| define void @store64_ashr_by_negated(i64 %val, ptr %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, ptr %dstptr |
| ret void |
| } |
| define void @modify64_ashr_by_negated(ptr %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, ptr %valptr |
| %negshamt = sub i64 64, %shamt |
| %shifted = ashr i64 %val, %negshamt |
| store i64 %shifted, ptr %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: movzbl {{[0-9]+}}(%esp), %edx |
| ; 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 |
| } |