mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-30 17:21:10 +00:00
[X86] Add test coverage for PR33879 (Issue #33226)
Ensure we only use the eflags results from shift instructions when it won't cause stalls shift by variable causes stalls as it has to preserve eflags when the shift amount was zero, so we're better off using a separate test
This commit is contained in:
parent
71a7192d69
commit
9405b67a9e
388
llvm/test/CodeGen/X86/shift-eflags.ll
Normal file
388
llvm/test/CodeGen/X86/shift-eflags.ll
Normal file
@ -0,0 +1,388 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc < %s -mtriple=x86_64-- | FileCheck %s
|
||||
|
||||
; PR33879 - use shift eflags result when it won't cause stalls
|
||||
|
||||
; ashr by constant - use sarl eflags result
|
||||
define i32 @ashr_const(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: ashr_const:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edx, %eax
|
||||
; CHECK-NEXT: sarl $14, %edi
|
||||
; CHECK-NEXT: cmovnel %ecx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = ashr i32 %a0, 14
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; lshr by constant - simplify to test
|
||||
define i32 @lshr_const(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: lshr_const:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edx, %eax
|
||||
; CHECK-NEXT: testl $-16384, %edi # imm = 0xC000
|
||||
; CHECK-NEXT: cmovnel %ecx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = lshr i32 %a0, 14
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; shl by constant - simplify to test
|
||||
define i32 @shl_const(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: shl_const:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edx, %eax
|
||||
; CHECK-NEXT: testl $262143, %edi # imm = 0x3FFFF
|
||||
; CHECK-NEXT: cmovnel %ecx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = shl i32 %a0, 14
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; ashr by constant and using shift result - use sarl eflags result
|
||||
define i32 @ashr_const_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: ashr_const_self_select:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: sarl $14, %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = ashr i32 %a0, 14
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; lshr by constant and using shift result - use shrl eflags result
|
||||
define i32 @lshr_const_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: lshr_const_self_select:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: shrl $14, %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = lshr i32 %a0, 14
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; lshr by constant and using result - use shll eflags result
|
||||
define i32 @shl_const_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: shl_const_self_select:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: shll $14, %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = shl i32 %a0, 14
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; ashr by 1 - use sarl eflags result
|
||||
define i32 @ashr_const1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: ashr_const1:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edx, %eax
|
||||
; CHECK-NEXT: sarl %edi
|
||||
; CHECK-NEXT: cmovnel %ecx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = ashr i32 %a0, 1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; lshr by 1 - simplify to test
|
||||
define i32 @lshr_const1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: lshr_const1:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edx, %eax
|
||||
; CHECK-NEXT: testl $-2, %edi
|
||||
; CHECK-NEXT: cmovnel %ecx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = lshr i32 %a0, 1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; shl by 1 - simplify to test
|
||||
define i32 @shl_const1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: shl_const1:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edx, %eax
|
||||
; CHECK-NEXT: testl $2147483647, %edi # imm = 0x7FFFFFFF
|
||||
; CHECK-NEXT: cmovnel %ecx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = shl i32 %a0, 1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; ashr by 1 and using shift result - use sarl eflags result
|
||||
define i32 @ashr_const1_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: ashr_const1_self_select:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: sarl %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = ashr i32 %a0, 1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; lshr by 1 and using shift result - use shrl eflags result
|
||||
define i32 @lshr_const1_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: lshr_const1_self_select:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: shrl %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = lshr i32 %a0, 1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; lshr by 1 and using result - use addl eflags result
|
||||
define i32 @shl_const1_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: shl_const1_self_select:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: addl %edi, %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = shl i32 %a0, 1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; ashr by variable - use seperate test
|
||||
define i32 @ashr_var(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: ashr_var:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %ecx, %eax
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: sarl %cl, %edi
|
||||
; CHECK-NEXT: testl %edi, %edi
|
||||
; CHECK-NEXT: cmovel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = ashr i32 %a0, %a1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; lshr by variable - use seperate test
|
||||
define i32 @lshr_var(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: lshr_var:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %ecx, %eax
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: shrl %cl, %edi
|
||||
; CHECK-NEXT: testl %edi, %edi
|
||||
; CHECK-NEXT: cmovel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = lshr i32 %a0, %a1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; shl by variable - use seperate test
|
||||
define i32 @shl_var(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: shl_var:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %ecx, %eax
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: shll %cl, %edi
|
||||
; CHECK-NEXT: testl %edi, %edi
|
||||
; CHECK-NEXT: cmovel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = shl i32 %a0, %a1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; ashr by variable and using result - use seperate test
|
||||
define i32 @ashr_var_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: ashr_var_self_select:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: sarl %cl, %eax
|
||||
; CHECK-NEXT: testl %eax, %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = ashr i32 %a0, %a1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; lshr by variable and using result - use seperate test
|
||||
define i32 @lshr_var_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: lshr_var_self_select:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: shrl %cl, %eax
|
||||
; CHECK-NEXT: testl %eax, %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = lshr i32 %a0, %a1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; shl by variable and using result - use seperate test
|
||||
define i32 @shl_var_self_select(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: shl_var_self_select:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: shll %cl, %eax
|
||||
; CHECK-NEXT: testl %eax, %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%s = shl i32 %a0, %a1
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; ashr by non-zero variable - use seperate test
|
||||
define i32 @ashr_var_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: ashr_var_amt_never_zero:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %ecx, %eax
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: orb $1, %cl
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: sarl %cl, %edi
|
||||
; CHECK-NEXT: testl %edi, %edi
|
||||
; CHECK-NEXT: cmovel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%a = or i32 %a1, 1
|
||||
%s = ashr i32 %a0, %a
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; lshr by non-zero variable - use seperate test
|
||||
define i32 @lshr_var_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: lshr_var_amt_never_zero:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %ecx, %eax
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: orb $1, %cl
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: shrl %cl, %edi
|
||||
; CHECK-NEXT: testl %edi, %edi
|
||||
; CHECK-NEXT: cmovel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%a = or i32 %a1, 1
|
||||
%s = lshr i32 %a0, %a
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; shl by non-zero variable - use seperate test
|
||||
define i32 @shl_var_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: shl_var_amt_never_zero:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %ecx, %eax
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: orb $1, %cl
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: shll %cl, %edi
|
||||
; CHECK-NEXT: testl %edi, %edi
|
||||
; CHECK-NEXT: cmovel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%a = or i32 %a1, 1
|
||||
%s = shl i32 %a0, %a
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %a2, i32 %a3
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; ashr by non-zero variable and using result - use seperate test
|
||||
define i32 @ashr_var_self_select_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: ashr_var_self_select_amt_never_zero:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: orb $1, %cl
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: shrl %cl, %eax
|
||||
; CHECK-NEXT: testl %eax, %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%a = or i32 %a1, 1
|
||||
%s = lshr i32 %a0, %a
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; lshr by non-zero variable and using result - use seperate test
|
||||
define i32 @lshr_var_self_select_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: lshr_var_self_select_amt_never_zero:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: orb $1, %cl
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: shrl %cl, %eax
|
||||
; CHECK-NEXT: testl %eax, %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%a = or i32 %a1, 1
|
||||
%s = lshr i32 %a0, %a
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
; shl by non-zero variable and using result - use seperate test
|
||||
define i32 @shl_var_self_select_amt_never_zero(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {
|
||||
; CHECK-LABEL: shl_var_self_select_amt_never_zero:
|
||||
; CHECK: # %bb.0:
|
||||
; CHECK-NEXT: movl %esi, %ecx
|
||||
; CHECK-NEXT: movl %edi, %eax
|
||||
; CHECK-NEXT: orb $1, %cl
|
||||
; CHECK-NEXT: # kill: def $cl killed $cl killed $ecx
|
||||
; CHECK-NEXT: shrl %cl, %eax
|
||||
; CHECK-NEXT: testl %eax, %eax
|
||||
; CHECK-NEXT: cmovnel %edx, %eax
|
||||
; CHECK-NEXT: retq
|
||||
%a = or i32 %a1, 1
|
||||
%s = lshr i32 %a0, %a
|
||||
%c = icmp eq i32 %s, 0
|
||||
%r = select i1 %c, i32 %s, i32 %a2
|
||||
ret i32 %r
|
||||
}
|
Loading…
Reference in New Issue
Block a user