Improve and enable folding of conditional branches with tail calls. 1. Make it so that conditional tail calls can be emitted even when there are multiple predecessors. 2. Don't guard the transformation behind -Os. The rationale for guarding it was static-prediction can be affected by whether the branch is forward of backward. This is no longer true for almost any X86 cpus (anything newer than `SnB`) so is no longer a meaningful concern. Reviewed By: pengfei Differential Revision: https://reviews.llvm.org/D140931
615 lines
20 KiB
LLVM
615 lines
20 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -mtriple=x86_64-- -mattr=+sse2 | FileCheck %s --check-prefix=SSE
|
|
; RUN: llc < %s -mtriple=x86_64-- -mattr=+avx | FileCheck %s --check-prefix=AVX
|
|
|
|
;
|
|
; SSE
|
|
;
|
|
|
|
define i32 @test_x86_sse_comieq_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_comieq_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: comiss %xmm1, %xmm0
|
|
; SSE-NEXT: setnp %cl
|
|
; SSE-NEXT: sete %dl
|
|
; SSE-NEXT: testb %cl, %dl
|
|
; SSE-NEXT: cmovnel %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_comieq_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vcomiss %xmm1, %xmm0
|
|
; AVX-NEXT: setnp %cl
|
|
; AVX-NEXT: sete %dl
|
|
; AVX-NEXT: testb %cl, %dl
|
|
; AVX-NEXT: cmovnel %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.comieq.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.comieq.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse_comige_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_comige_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: comiss %xmm1, %xmm0
|
|
; SSE-NEXT: cmovbl %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_comige_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vcomiss %xmm1, %xmm0
|
|
; AVX-NEXT: cmovbl %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.comige.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.comige.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse_comigt_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_comigt_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: comiss %xmm1, %xmm0
|
|
; SSE-NEXT: cmoval %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_comigt_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vcomiss %xmm1, %xmm0
|
|
; AVX-NEXT: cmoval %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.comigt.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.comigt.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse_comile_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_comile_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: comiss %xmm0, %xmm1
|
|
; SSE-NEXT: cmovbl %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_comile_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vcomiss %xmm0, %xmm1
|
|
; AVX-NEXT: cmovbl %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.comile.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.comile.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse_comilt_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_comilt_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: comiss %xmm0, %xmm1
|
|
; SSE-NEXT: cmoval %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_comilt_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vcomiss %xmm0, %xmm1
|
|
; AVX-NEXT: cmoval %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.comilt.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.comilt.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse_comineq_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_comineq_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %esi, %eax
|
|
; SSE-NEXT: comiss %xmm1, %xmm0
|
|
; SSE-NEXT: cmovnel %edi, %eax
|
|
; SSE-NEXT: cmovpl %edi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_comineq_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %esi, %eax
|
|
; AVX-NEXT: vcomiss %xmm1, %xmm0
|
|
; AVX-NEXT: cmovnel %edi, %eax
|
|
; AVX-NEXT: cmovpl %edi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.comineq.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.comineq.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse_ucomieq_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_ucomieq_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: ucomiss %xmm1, %xmm0
|
|
; SSE-NEXT: setnp %cl
|
|
; SSE-NEXT: sete %dl
|
|
; SSE-NEXT: testb %cl, %dl
|
|
; SSE-NEXT: cmovnel %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_ucomieq_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vucomiss %xmm1, %xmm0
|
|
; AVX-NEXT: setnp %cl
|
|
; AVX-NEXT: sete %dl
|
|
; AVX-NEXT: testb %cl, %dl
|
|
; AVX-NEXT: cmovnel %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.ucomieq.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.ucomieq.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse_ucomige_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_ucomige_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: ucomiss %xmm1, %xmm0
|
|
; SSE-NEXT: cmovbl %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_ucomige_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vucomiss %xmm1, %xmm0
|
|
; AVX-NEXT: cmovbl %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.ucomige.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.ucomige.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse_ucomigt_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_ucomigt_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: ucomiss %xmm1, %xmm0
|
|
; SSE-NEXT: cmoval %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_ucomigt_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vucomiss %xmm1, %xmm0
|
|
; AVX-NEXT: cmoval %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.ucomigt.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.ucomigt.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse_ucomile_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_ucomile_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: ucomiss %xmm0, %xmm1
|
|
; SSE-NEXT: cmovbl %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_ucomile_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vucomiss %xmm0, %xmm1
|
|
; AVX-NEXT: cmovbl %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.ucomile.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.ucomile.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse_ucomilt_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_ucomilt_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: ucomiss %xmm0, %xmm1
|
|
; SSE-NEXT: cmoval %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_ucomilt_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vucomiss %xmm0, %xmm1
|
|
; AVX-NEXT: cmoval %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.ucomilt.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.ucomilt.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse_ucomineq_ss(<4 x float> %a0, <4 x float> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse_ucomineq_ss:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %esi, %eax
|
|
; SSE-NEXT: ucomiss %xmm1, %xmm0
|
|
; SSE-NEXT: cmovnel %edi, %eax
|
|
; SSE-NEXT: cmovpl %edi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse_ucomineq_ss:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %esi, %eax
|
|
; AVX-NEXT: vucomiss %xmm1, %xmm0
|
|
; AVX-NEXT: cmovnel %edi, %eax
|
|
; AVX-NEXT: cmovpl %edi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse.ucomineq.ss(<4 x float> %a0, <4 x float> %a1)
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse.ucomineq.ss(<4 x float>, <4 x float>) nounwind readnone
|
|
|
|
;
|
|
; SSE2
|
|
;
|
|
|
|
define i32 @test_x86_sse2_comieq_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_comieq_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: comisd %xmm1, %xmm0
|
|
; SSE-NEXT: setnp %cl
|
|
; SSE-NEXT: sete %dl
|
|
; SSE-NEXT: testb %cl, %dl
|
|
; SSE-NEXT: cmovnel %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_comieq_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vcomisd %xmm1, %xmm0
|
|
; AVX-NEXT: setnp %cl
|
|
; AVX-NEXT: sete %dl
|
|
; AVX-NEXT: testb %cl, %dl
|
|
; AVX-NEXT: cmovnel %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.comieq.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.comieq.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse2_comige_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_comige_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: comisd %xmm1, %xmm0
|
|
; SSE-NEXT: cmovbl %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_comige_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vcomisd %xmm1, %xmm0
|
|
; AVX-NEXT: cmovbl %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.comige.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.comige.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse2_comigt_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_comigt_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: comisd %xmm1, %xmm0
|
|
; SSE-NEXT: cmoval %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_comigt_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vcomisd %xmm1, %xmm0
|
|
; AVX-NEXT: cmoval %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.comigt.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.comigt.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse2_comile_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_comile_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: comisd %xmm0, %xmm1
|
|
; SSE-NEXT: cmovbl %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_comile_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vcomisd %xmm0, %xmm1
|
|
; AVX-NEXT: cmovbl %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.comile.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.comile.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse2_comilt_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_comilt_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: comisd %xmm0, %xmm1
|
|
; SSE-NEXT: cmoval %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_comilt_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vcomisd %xmm0, %xmm1
|
|
; AVX-NEXT: cmoval %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.comilt.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.comilt.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse2_comineq_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_comineq_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %esi, %eax
|
|
; SSE-NEXT: comisd %xmm1, %xmm0
|
|
; SSE-NEXT: cmovnel %edi, %eax
|
|
; SSE-NEXT: cmovpl %edi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_comineq_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %esi, %eax
|
|
; AVX-NEXT: vcomisd %xmm1, %xmm0
|
|
; AVX-NEXT: cmovnel %edi, %eax
|
|
; AVX-NEXT: cmovpl %edi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.comineq.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.comineq.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse2_ucomieq_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_ucomieq_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: ucomisd %xmm1, %xmm0
|
|
; SSE-NEXT: setnp %cl
|
|
; SSE-NEXT: sete %dl
|
|
; SSE-NEXT: testb %cl, %dl
|
|
; SSE-NEXT: cmovnel %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_ucomieq_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vucomisd %xmm1, %xmm0
|
|
; AVX-NEXT: setnp %cl
|
|
; AVX-NEXT: sete %dl
|
|
; AVX-NEXT: testb %cl, %dl
|
|
; AVX-NEXT: cmovnel %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.ucomieq.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.ucomieq.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse2_ucomige_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_ucomige_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: ucomisd %xmm1, %xmm0
|
|
; SSE-NEXT: cmovbl %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_ucomige_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vucomisd %xmm1, %xmm0
|
|
; AVX-NEXT: cmovbl %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.ucomige.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.ucomige.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse2_ucomigt_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_ucomigt_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: ucomisd %xmm1, %xmm0
|
|
; SSE-NEXT: cmoval %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_ucomigt_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vucomisd %xmm1, %xmm0
|
|
; AVX-NEXT: cmoval %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.ucomigt.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.ucomigt.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse2_ucomile_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_ucomile_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: ucomisd %xmm0, %xmm1
|
|
; SSE-NEXT: cmovbl %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_ucomile_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vucomisd %xmm0, %xmm1
|
|
; AVX-NEXT: cmovbl %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.ucomile.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.ucomile.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse2_ucomilt_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_ucomilt_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %edi, %eax
|
|
; SSE-NEXT: ucomisd %xmm0, %xmm1
|
|
; SSE-NEXT: cmoval %esi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_ucomilt_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %edi, %eax
|
|
; AVX-NEXT: vucomisd %xmm0, %xmm1
|
|
; AVX-NEXT: cmoval %esi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.ucomilt.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp eq i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.ucomilt.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define i32 @test_x86_sse2_ucomineq_sd(<2 x double> %a0, <2 x double> %a1, i32 %a2, i32 %a3) {
|
|
; SSE-LABEL: test_x86_sse2_ucomineq_sd:
|
|
; SSE: # %bb.0:
|
|
; SSE-NEXT: movl %esi, %eax
|
|
; SSE-NEXT: ucomisd %xmm1, %xmm0
|
|
; SSE-NEXT: cmovnel %edi, %eax
|
|
; SSE-NEXT: cmovpl %edi, %eax
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: test_x86_sse2_ucomineq_sd:
|
|
; AVX: # %bb.0:
|
|
; AVX-NEXT: movl %esi, %eax
|
|
; AVX-NEXT: vucomisd %xmm1, %xmm0
|
|
; AVX-NEXT: cmovnel %edi, %eax
|
|
; AVX-NEXT: cmovpl %edi, %eax
|
|
; AVX-NEXT: retq
|
|
%call = call i32 @llvm.x86.sse2.ucomineq.sd(<2 x double> %a0, <2 x double> %a1) ; <i32> [#uses=1]
|
|
%cmp = icmp ne i32 %call, 0
|
|
%res = select i1 %cmp, i32 %a2, i32 %a3
|
|
ret i32 %res
|
|
}
|
|
declare i32 @llvm.x86.sse2.ucomineq.sd(<2 x double>, <2 x double>) nounwind readnone
|
|
|
|
define void @PR38960_eq(<4 x float> %A, <4 x float> %B) {
|
|
; SSE-LABEL: PR38960_eq:
|
|
; SSE: # %bb.0: # %entry
|
|
; SSE-NEXT: comiss %xmm1, %xmm0
|
|
; SSE-NEXT: setnp %al
|
|
; SSE-NEXT: sete %cl
|
|
; SSE-NEXT: testb %al, %cl
|
|
; SSE-NEXT: jne foo@PLT # TAILCALL
|
|
; SSE-NEXT: # %bb.1: # %if.end
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: PR38960_eq:
|
|
; AVX: # %bb.0: # %entry
|
|
; AVX-NEXT: vcomiss %xmm1, %xmm0
|
|
; AVX-NEXT: setnp %al
|
|
; AVX-NEXT: sete %cl
|
|
; AVX-NEXT: testb %al, %cl
|
|
; AVX-NEXT: jne foo@PLT # TAILCALL
|
|
; AVX-NEXT: # %bb.1: # %if.end
|
|
; AVX-NEXT: retq
|
|
entry:
|
|
%call = tail call i32 @llvm.x86.sse.comieq.ss(<4 x float> %A, <4 x float> %B) #3
|
|
%cmp = icmp eq i32 %call, 0
|
|
br i1 %cmp, label %if.end, label %if.then
|
|
|
|
if.then:
|
|
tail call void @foo()
|
|
br label %if.end
|
|
|
|
if.end:
|
|
ret void
|
|
}
|
|
|
|
define void @PR38960_neq(<4 x float> %A, <4 x float> %B) {
|
|
; SSE-LABEL: PR38960_neq:
|
|
; SSE: # %bb.0: # %entry
|
|
; SSE-NEXT: comiss %xmm1, %xmm0
|
|
; SSE-NEXT: setp %al
|
|
; SSE-NEXT: setne %cl
|
|
; SSE-NEXT: orb %al, %cl
|
|
; SSE-NEXT: jne foo@PLT # TAILCALL
|
|
; SSE-NEXT: # %bb.1: # %if.end
|
|
; SSE-NEXT: retq
|
|
;
|
|
; AVX-LABEL: PR38960_neq:
|
|
; AVX: # %bb.0: # %entry
|
|
; AVX-NEXT: vcomiss %xmm1, %xmm0
|
|
; AVX-NEXT: setp %al
|
|
; AVX-NEXT: setne %cl
|
|
; AVX-NEXT: orb %al, %cl
|
|
; AVX-NEXT: jne foo@PLT # TAILCALL
|
|
; AVX-NEXT: # %bb.1: # %if.end
|
|
; AVX-NEXT: retq
|
|
entry:
|
|
%call = tail call i32 @llvm.x86.sse.comineq.ss(<4 x float> %A, <4 x float> %B) #3
|
|
%cmp = icmp eq i32 %call, 0
|
|
br i1 %cmp, label %if.end, label %if.then
|
|
|
|
if.then:
|
|
tail call void @foo()
|
|
br label %if.end
|
|
|
|
if.end:
|
|
ret void
|
|
}
|
|
declare void @foo()
|