forked from OSchip/llvm-project
[X86] Add strict fp support for operations of X87 instructions
This is the following patch of D68854. This patch adds basic operations of X87 instructions, including +, -, *, / , fp extensions and fp truncations. Patch by Chen Liu(LiuChen3) Differential Revision: https://reviews.llvm.org/D68857
This commit is contained in:
parent
b8cb73dd38
commit
cfce8f2cfb
|
@ -5222,12 +5222,20 @@ void X86DAGToDAGISel::Select(SDNode *Node) {
|
|||
}
|
||||
case ISD::STRICT_FADD:
|
||||
case ISD::STRICT_FSUB:
|
||||
case ISD::STRICT_FP_ROUND: {
|
||||
// X87 instructions has enabled these strict fp operation.
|
||||
bool UsingFp80 = Node->getSimpleValueType(0) == MVT::f80 ||
|
||||
Node->getOperand(1).getSimpleValueType() == MVT::f80;
|
||||
if (UsingFp80 || (!Subtarget->hasSSE1() && Subtarget->hasX87()))
|
||||
break;
|
||||
LLVM_FALLTHROUGH;
|
||||
}
|
||||
case ISD::STRICT_FP_TO_SINT:
|
||||
case ISD::STRICT_FP_TO_UINT:
|
||||
case ISD::STRICT_FP_ROUND:
|
||||
// FIXME: Remove when we have isel patterns for strict versions of these
|
||||
// nodes.
|
||||
CurDAG->mutateStrictFPToFP(Node);
|
||||
if (!TLI->isStrictFPEnabled())
|
||||
CurDAG->mutateStrictFPToFP(Node);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -587,6 +587,15 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
|
|||
setOperationAction(ISD::FSIN , VT, Expand);
|
||||
setOperationAction(ISD::FCOS , VT, Expand);
|
||||
setOperationAction(ISD::FSINCOS, VT, Expand);
|
||||
|
||||
// Handle constrained floating-point operations of scalar.
|
||||
setOperationAction(ISD::STRICT_FMUL , VT, Legal);
|
||||
setOperationAction(ISD::STRICT_FDIV , VT, Legal);
|
||||
setOperationAction(ISD::STRICT_FSQRT , VT, Legal);
|
||||
setOperationAction(ISD::STRICT_FP_EXTEND, VT, Legal);
|
||||
// FIXME: When the target is 64-bit, STRICT_FP_ROUND will be overwritten
|
||||
// as Custom.
|
||||
setOperationAction(ISD::STRICT_FP_ROUND, VT, Legal);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -657,6 +666,17 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
|
|||
setOperationAction(ISD::LLROUND, MVT::f80, Expand);
|
||||
setOperationAction(ISD::LRINT, MVT::f80, Expand);
|
||||
setOperationAction(ISD::LLRINT, MVT::f80, Expand);
|
||||
|
||||
// Handle constrained floating-point operations of scalar.
|
||||
setOperationAction(ISD::STRICT_FADD , MVT::f80, Legal);
|
||||
setOperationAction(ISD::STRICT_FSUB , MVT::f80, Legal);
|
||||
setOperationAction(ISD::STRICT_FMUL , MVT::f80, Legal);
|
||||
setOperationAction(ISD::STRICT_FDIV , MVT::f80, Legal);
|
||||
setOperationAction(ISD::STRICT_FSQRT , MVT::f80, Legal);
|
||||
setOperationAction(ISD::STRICT_FP_EXTEND, MVT::f80, Legal);
|
||||
// FIXME: When the target is 64-bit, STRICT_FP_ROUND will be overwritten
|
||||
// as Custom.
|
||||
setOperationAction(ISD::STRICT_FP_ROUND, MVT::f80, Legal);
|
||||
}
|
||||
|
||||
// f128 uses xmm registers, but most operations require libcalls.
|
||||
|
|
|
@ -286,26 +286,26 @@ let Uses = [FPCW], mayRaiseFPException = 1 in {
|
|||
// FPBinary_rr just defines pseudo-instructions, no need to set a scheduling
|
||||
// resources.
|
||||
let hasNoSchedulingInfo = 1 in {
|
||||
defm ADD : FPBinary_rr<fadd>;
|
||||
defm SUB : FPBinary_rr<fsub>;
|
||||
defm MUL : FPBinary_rr<fmul>;
|
||||
defm DIV : FPBinary_rr<fdiv>;
|
||||
defm ADD : FPBinary_rr<any_fadd>;
|
||||
defm SUB : FPBinary_rr<any_fsub>;
|
||||
defm MUL : FPBinary_rr<any_fmul>;
|
||||
defm DIV : FPBinary_rr<any_fdiv>;
|
||||
}
|
||||
|
||||
// Sets the scheduling resources for the actual NAME#_F<size>m defintions.
|
||||
let SchedRW = [WriteFAddLd] in {
|
||||
defm ADD : FPBinary<fadd, MRM0m, "add">;
|
||||
defm SUB : FPBinary<fsub, MRM4m, "sub">;
|
||||
defm SUBR: FPBinary<fsub ,MRM5m, "subr", 0>;
|
||||
defm ADD : FPBinary<any_fadd, MRM0m, "add">;
|
||||
defm SUB : FPBinary<any_fsub, MRM4m, "sub">;
|
||||
defm SUBR: FPBinary<any_fsub ,MRM5m, "subr", 0>;
|
||||
}
|
||||
|
||||
let SchedRW = [WriteFMulLd] in {
|
||||
defm MUL : FPBinary<fmul, MRM1m, "mul">;
|
||||
defm MUL : FPBinary<any_fmul, MRM1m, "mul">;
|
||||
}
|
||||
|
||||
let SchedRW = [WriteFDivLd] in {
|
||||
defm DIV : FPBinary<fdiv, MRM6m, "div">;
|
||||
defm DIVR: FPBinary<fdiv, MRM7m, "divr", 0>;
|
||||
defm DIV : FPBinary<any_fdiv, MRM6m, "div">;
|
||||
defm DIVR: FPBinary<any_fdiv, MRM7m, "divr", 0>;
|
||||
}
|
||||
} // Uses = [FPCW], mayRaiseFPException = 1
|
||||
|
||||
|
@ -366,7 +366,7 @@ defm ABS : FPUnary<fabs, MRM_E1, "fabs">;
|
|||
|
||||
let Uses = [FPCW], mayRaiseFPException = 1 in {
|
||||
let SchedRW = [WriteFSqrt80] in
|
||||
defm SQRT: FPUnary<fsqrt,MRM_FA, "fsqrt">;
|
||||
defm SQRT: FPUnary<any_fsqrt,MRM_FA, "fsqrt">;
|
||||
|
||||
let SchedRW = [WriteFCom] in {
|
||||
let hasSideEffects = 0 in {
|
||||
|
@ -790,19 +790,19 @@ def : Pat<(X86fist64 RFP80:$src, addr:$op), (IST_Fp64m80 addr:$op, RFP80:$src)>;
|
|||
|
||||
// FP extensions map onto simple pseudo-value conversions if they are to/from
|
||||
// the FP stack.
|
||||
def : Pat<(f64 (fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP64)>,
|
||||
def : Pat<(f64 (any_fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP64)>,
|
||||
Requires<[FPStackf32]>;
|
||||
def : Pat<(f80 (fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP80)>,
|
||||
def : Pat<(f80 (any_fpextend RFP32:$src)), (COPY_TO_REGCLASS RFP32:$src, RFP80)>,
|
||||
Requires<[FPStackf32]>;
|
||||
def : Pat<(f80 (fpextend RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP80)>,
|
||||
def : Pat<(f80 (any_fpextend RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP80)>,
|
||||
Requires<[FPStackf64]>;
|
||||
|
||||
// FP truncations map onto simple pseudo-value conversions if they are to/from
|
||||
// the FP stack. We have validated that only value-preserving truncations make
|
||||
// it through isel.
|
||||
def : Pat<(f32 (fpround RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP32)>,
|
||||
def : Pat<(f32 (any_fpround RFP64:$src)), (COPY_TO_REGCLASS RFP64:$src, RFP32)>,
|
||||
Requires<[FPStackf32]>;
|
||||
def : Pat<(f32 (fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP32)>,
|
||||
def : Pat<(f32 (any_fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP32)>,
|
||||
Requires<[FPStackf32]>;
|
||||
def : Pat<(f64 (fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP64)>,
|
||||
def : Pat<(f64 (any_fpround RFP80:$src)), (COPY_TO_REGCLASS RFP80:$src, RFP64)>,
|
||||
Requires<[FPStackf64]>;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx -O3 | FileCheck %s --check-prefixes=CHECK,AVX,AVX-X64
|
||||
; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+avx512f -mattr=+avx512vl -O3 | FileCheck %s --check-prefixes=CHECK,AVX,AVX-X86
|
||||
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f -mattr=+avx512vl -O3 | FileCheck %s --check-prefixes=CHECK,AVX,AVX-X64
|
||||
; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=-sse -O3 | FileCheck %s --check-prefixes=CHECK,X87
|
||||
; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=-sse -O3 -disable-strictnode-mutation | FileCheck %s --check-prefixes=CHECK,X87
|
||||
|
||||
declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata)
|
||||
declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc < %s -mtriple=i686-unknown-unknown -O3 | FileCheck %s --check-prefixes=CHECK,X86
|
||||
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -O3 | FileCheck %s --check-prefixes=CHECK,X64
|
||||
; RUN: llc < %s -mtriple=i686-unknown-unknown -O3 -disable-strictnode-mutation | FileCheck %s --check-prefixes=CHECK,X86
|
||||
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -O3 -disable-strictnode-mutation | FileCheck %s --check-prefixes=CHECK,X64
|
||||
|
||||
declare x86_fp80 @llvm.experimental.constrained.fadd.x86_fp80(x86_fp80, x86_fp80, metadata, metadata)
|
||||
declare x86_fp80 @llvm.experimental.constrained.fsub.x86_fp80(x86_fp80, x86_fp80, metadata, metadata)
|
||||
|
|
Loading…
Reference in New Issue