mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
Model sqrtss as a binary operation with one source operand tied to the destination (PR14221)
This is a continuation of r167064 ( http://llvm.org/viewvc/llvm-project?view=revision&revision=167064 ). That patch started to fix PR14221 ( http://llvm.org/bugs/show_bug.cgi?id=14221 ), but it was not completed. Differential Revision: http://reviews.llvm.org/D6330 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224624 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2516f059db
commit
9ccbf1a260
@ -3536,57 +3536,10 @@ def SSE_RCPS : OpndItins<
|
|||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// sse1_fp_unop_s - SSE1 unops in scalar form.
|
/// sse1_fp_unop_s - SSE1 unops in scalar form
|
||||||
multiclass sse1_fp_unop_s<bits<8> opc, string OpcodeStr,
|
/// For the non-AVX defs, we need $src1 to be tied to $dst because
|
||||||
SDNode OpNode, Intrinsic F32Int, OpndItins itins> {
|
/// the HW instructions are 2 operand / destructive.
|
||||||
let Predicates = [HasAVX], hasSideEffects = 0 in {
|
multiclass sse1_fp_unop_s<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
||||||
def V#NAME#SSr : SSI<opc, MRMSrcReg, (outs FR32:$dst),
|
|
||||||
(ins FR32:$src1, FR32:$src2),
|
|
||||||
!strconcat("v", OpcodeStr,
|
|
||||||
"ss\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
|
||||||
[]>, VEX_4V, VEX_LIG, Sched<[itins.Sched]>;
|
|
||||||
let mayLoad = 1 in {
|
|
||||||
def V#NAME#SSm : SSI<opc, MRMSrcMem, (outs FR32:$dst),
|
|
||||||
(ins FR32:$src1,f32mem:$src2),
|
|
||||||
!strconcat("v", OpcodeStr,
|
|
||||||
"ss\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
|
||||||
[]>, VEX_4V, VEX_LIG,
|
|
||||||
Sched<[itins.Sched.Folded, ReadAfterLd]>;
|
|
||||||
let isCodeGenOnly = 1 in
|
|
||||||
def V#NAME#SSm_Int : SSI<opc, MRMSrcMem, (outs VR128:$dst),
|
|
||||||
(ins VR128:$src1, ssmem:$src2),
|
|
||||||
!strconcat("v", OpcodeStr,
|
|
||||||
"ss\t{$src2, $src1, $dst|$dst, $src1, $src2}"),
|
|
||||||
[]>, VEX_4V, VEX_LIG,
|
|
||||||
Sched<[itins.Sched.Folded, ReadAfterLd]>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def SSr : SSI<opc, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src),
|
|
||||||
!strconcat(OpcodeStr, "ss\t{$src, $dst|$dst, $src}"),
|
|
||||||
[(set FR32:$dst, (OpNode FR32:$src))]>, Sched<[itins.Sched]>;
|
|
||||||
// For scalar unary operations, fold a load into the operation
|
|
||||||
// only in OptForSize mode. It eliminates an instruction, but it also
|
|
||||||
// eliminates a whole-register clobber (the load), so it introduces a
|
|
||||||
// partial register update condition.
|
|
||||||
def SSm : I<opc, MRMSrcMem, (outs FR32:$dst), (ins f32mem:$src),
|
|
||||||
!strconcat(OpcodeStr, "ss\t{$src, $dst|$dst, $src}"),
|
|
||||||
[(set FR32:$dst, (OpNode (load addr:$src)))], itins.rm>, XS,
|
|
||||||
Requires<[UseSSE1, OptForSize]>, Sched<[itins.Sched.Folded]>;
|
|
||||||
let isCodeGenOnly = 1 in {
|
|
||||||
def SSr_Int : SSI<opc, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
|
|
||||||
!strconcat(OpcodeStr, "ss\t{$src, $dst|$dst, $src}"),
|
|
||||||
[(set VR128:$dst, (F32Int VR128:$src))], itins.rr>,
|
|
||||||
Sched<[itins.Sched]>;
|
|
||||||
def SSm_Int : SSI<opc, MRMSrcMem, (outs VR128:$dst), (ins ssmem:$src),
|
|
||||||
!strconcat(OpcodeStr, "ss\t{$src, $dst|$dst, $src}"),
|
|
||||||
[(set VR128:$dst, (F32Int sse_load_f32:$src))], itins.rm>,
|
|
||||||
Sched<[itins.Sched.Folded]>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// sse1_fp_unop_s_rw - SSE1 unops where vector form has a read-write operand.
|
|
||||||
multiclass sse1_fp_unop_rw<bits<8> opc, string OpcodeStr, SDNode OpNode,
|
|
||||||
OpndItins itins> {
|
OpndItins itins> {
|
||||||
let Predicates = [HasAVX], hasSideEffects = 0 in {
|
let Predicates = [HasAVX], hasSideEffects = 0 in {
|
||||||
def V#NAME#SSr : SSI<opc, MRMSrcReg, (outs FR32:$dst),
|
def V#NAME#SSr : SSI<opc, MRMSrcReg, (outs FR32:$dst),
|
||||||
@ -3795,20 +3748,19 @@ let Predicates = [HasAVX] in {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Square root.
|
// Square root.
|
||||||
defm SQRT : sse1_fp_unop_s<0x51, "sqrt", fsqrt, int_x86_sse_sqrt_ss,
|
defm SQRT : sse1_fp_unop_s<0x51, "sqrt", fsqrt, SSE_SQRTSS>,
|
||||||
SSE_SQRTSS>,
|
|
||||||
sse1_fp_unop_p<0x51, "sqrt", fsqrt, SSE_SQRTPS>,
|
sse1_fp_unop_p<0x51, "sqrt", fsqrt, SSE_SQRTPS>,
|
||||||
sse2_fp_unop_s<0x51, "sqrt", fsqrt, int_x86_sse2_sqrt_sd,
|
sse2_fp_unop_s<0x51, "sqrt", fsqrt, int_x86_sse2_sqrt_sd,
|
||||||
SSE_SQRTSD>,
|
SSE_SQRTSD>,
|
||||||
sse2_fp_unop_p<0x51, "sqrt", fsqrt, SSE_SQRTPD>;
|
sse2_fp_unop_p<0x51, "sqrt", fsqrt, SSE_SQRTPD>;
|
||||||
|
|
||||||
// Reciprocal approximations. Note that these typically require refinement
|
// Reciprocal approximations. Note that these typically require refinement
|
||||||
// in order to obtain suitable precision.
|
// in order to obtain suitable precision.
|
||||||
defm RSQRT : sse1_fp_unop_rw<0x52, "rsqrt", X86frsqrt, SSE_RSQRTSS>,
|
defm RSQRT : sse1_fp_unop_s<0x52, "rsqrt", X86frsqrt, SSE_RSQRTSS>,
|
||||||
sse1_fp_unop_p<0x52, "rsqrt", X86frsqrt, SSE_RSQRTPS>,
|
sse1_fp_unop_p<0x52, "rsqrt", X86frsqrt, SSE_RSQRTPS>,
|
||||||
sse1_fp_unop_p_int<0x52, "rsqrt", int_x86_sse_rsqrt_ps,
|
sse1_fp_unop_p_int<0x52, "rsqrt", int_x86_sse_rsqrt_ps,
|
||||||
int_x86_avx_rsqrt_ps_256, SSE_RSQRTPS>;
|
int_x86_avx_rsqrt_ps_256, SSE_RSQRTPS>;
|
||||||
defm RCP : sse1_fp_unop_rw<0x53, "rcp", X86frcp, SSE_RCPS>,
|
defm RCP : sse1_fp_unop_s<0x53, "rcp", X86frcp, SSE_RCPS>,
|
||||||
sse1_fp_unop_p<0x53, "rcp", X86frcp, SSE_RCPP>,
|
sse1_fp_unop_p<0x53, "rcp", X86frcp, SSE_RCPP>,
|
||||||
sse1_fp_unop_p_int<0x53, "rcp", int_x86_sse_rcp_ps,
|
sse1_fp_unop_p_int<0x53, "rcp", int_x86_sse_rcp_ps,
|
||||||
int_x86_avx_rcp_ps_256, SSE_RCPP>;
|
int_x86_avx_rcp_ps_256, SSE_RCPP>;
|
||||||
@ -3869,13 +3821,15 @@ let Predicates = [HasAVX] in {
|
|||||||
(VRCPSSm_Int (v4f32 (IMPLICIT_DEF)), sse_load_f32:$src)>;
|
(VRCPSSm_Int (v4f32 (IMPLICIT_DEF)), sse_load_f32:$src)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reciprocal approximations. Note that these typically require refinement
|
// These are unary operations, but they are modeled as having 2 source operands
|
||||||
// in order to obtain suitable precision.
|
// because the high elements of the destination are unchanged in SSE.
|
||||||
let Predicates = [UseSSE1] in {
|
let Predicates = [UseSSE1] in {
|
||||||
def : Pat<(int_x86_sse_rsqrt_ss VR128:$src),
|
def : Pat<(int_x86_sse_rsqrt_ss VR128:$src),
|
||||||
(RSQRTSSr_Int VR128:$src, VR128:$src)>;
|
(RSQRTSSr_Int VR128:$src, VR128:$src)>;
|
||||||
def : Pat<(int_x86_sse_rcp_ss VR128:$src),
|
def : Pat<(int_x86_sse_rcp_ss VR128:$src),
|
||||||
(RCPSSr_Int VR128:$src, VR128:$src)>;
|
(RCPSSr_Int VR128:$src, VR128:$src)>;
|
||||||
|
def : Pat<(int_x86_sse_sqrt_ss VR128:$src),
|
||||||
|
(SQRTSSr_Int VR128:$src, VR128:$src)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// There is no f64 version of the reciprocal approximation instructions.
|
// There is no f64 version of the reciprocal approximation instructions.
|
||||||
|
@ -5,11 +5,18 @@
|
|||||||
; There is a mismatch between the intrinsic and the actual instruction.
|
; There is a mismatch between the intrinsic and the actual instruction.
|
||||||
; The actual instruction has a partial update of dest, while the intrinsic
|
; The actual instruction has a partial update of dest, while the intrinsic
|
||||||
; passes through the upper FP values. Here, we make sure the source and
|
; passes through the upper FP values. Here, we make sure the source and
|
||||||
; destination of rsqrtss are the same.
|
; destination of each scalar unary op are the same.
|
||||||
define void @t1(<4 x float> %a) nounwind uwtable ssp {
|
|
||||||
|
define void @rsqrtss(<4 x float> %a) nounwind uwtable ssp {
|
||||||
entry:
|
entry:
|
||||||
; CHECK-LABEL: t1:
|
; CHECK-LABEL: rsqrtss:
|
||||||
; CHECK: rsqrtss %xmm0, %xmm0
|
; CHECK: rsqrtss %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: cvtss2sd %xmm0
|
||||||
|
; CHECK-NEXT: shufps
|
||||||
|
; CHECK-NEXT: cvtss2sd %xmm0
|
||||||
|
; CHECK-NEXT: movap
|
||||||
|
; CHECK-NEXT: jmp
|
||||||
|
|
||||||
%0 = tail call <4 x float> @llvm.x86.sse.rsqrt.ss(<4 x float> %a) nounwind
|
%0 = tail call <4 x float> @llvm.x86.sse.rsqrt.ss(<4 x float> %a) nounwind
|
||||||
%a.addr.0.extract = extractelement <4 x float> %0, i32 0
|
%a.addr.0.extract = extractelement <4 x float> %0, i32 0
|
||||||
%conv = fpext float %a.addr.0.extract to double
|
%conv = fpext float %a.addr.0.extract to double
|
||||||
@ -21,10 +28,16 @@ entry:
|
|||||||
declare void @callee(double, double)
|
declare void @callee(double, double)
|
||||||
declare <4 x float> @llvm.x86.sse.rsqrt.ss(<4 x float>) nounwind readnone
|
declare <4 x float> @llvm.x86.sse.rsqrt.ss(<4 x float>) nounwind readnone
|
||||||
|
|
||||||
define void @t2(<4 x float> %a) nounwind uwtable ssp {
|
define void @rcpss(<4 x float> %a) nounwind uwtable ssp {
|
||||||
entry:
|
entry:
|
||||||
; CHECK-LABEL: t2:
|
; CHECK-LABEL: rcpss:
|
||||||
; CHECK: rcpss %xmm0, %xmm0
|
; CHECK: rcpss %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: cvtss2sd %xmm0
|
||||||
|
; CHECK-NEXT: shufps
|
||||||
|
; CHECK-NEXT: cvtss2sd %xmm0
|
||||||
|
; CHECK-NEXT: movap
|
||||||
|
; CHECK-NEXT: jmp
|
||||||
|
|
||||||
%0 = tail call <4 x float> @llvm.x86.sse.rcp.ss(<4 x float> %a) nounwind
|
%0 = tail call <4 x float> @llvm.x86.sse.rcp.ss(<4 x float> %a) nounwind
|
||||||
%a.addr.0.extract = extractelement <4 x float> %0, i32 0
|
%a.addr.0.extract = extractelement <4 x float> %0, i32 0
|
||||||
%conv = fpext float %a.addr.0.extract to double
|
%conv = fpext float %a.addr.0.extract to double
|
||||||
@ -34,3 +47,23 @@ entry:
|
|||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
declare <4 x float> @llvm.x86.sse.rcp.ss(<4 x float>) nounwind readnone
|
declare <4 x float> @llvm.x86.sse.rcp.ss(<4 x float>) nounwind readnone
|
||||||
|
|
||||||
|
define void @sqrtss(<4 x float> %a) nounwind uwtable ssp {
|
||||||
|
entry:
|
||||||
|
; CHECK-LABEL: sqrtss:
|
||||||
|
; CHECK: sqrtss %xmm0, %xmm0
|
||||||
|
; CHECK-NEXT: cvtss2sd %xmm0
|
||||||
|
; CHECK-NEXT: shufps
|
||||||
|
; CHECK-NEXT: cvtss2sd %xmm0
|
||||||
|
; CHECK-NEXT: movap
|
||||||
|
; CHECK-NEXT: jmp
|
||||||
|
|
||||||
|
%0 = tail call <4 x float> @llvm.x86.sse.sqrt.ss(<4 x float> %a) nounwind
|
||||||
|
%a.addr.0.extract = extractelement <4 x float> %0, i32 0
|
||||||
|
%conv = fpext float %a.addr.0.extract to double
|
||||||
|
%a.addr.4.extract = extractelement <4 x float> %0, i32 1
|
||||||
|
%conv3 = fpext float %a.addr.4.extract to double
|
||||||
|
tail call void @callee(double %conv, double %conv3) nounwind
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
declare <4 x float> @llvm.x86.sse.sqrt.ss(<4 x float>) nounwind readnone
|
||||||
|
Loading…
Reference in New Issue
Block a user