diff options
author | Craig Topper <craig.topper@gmail.com> | 2020-01-10 21:14:47 -0800 |
---|---|---|
committer | Craig Topper <craig.topper@gmail.com> | 2020-01-10 23:41:06 -0800 |
commit | 5fe5c0a60f9a5f32da4316ba0d1732a1e439703b (patch) | |
tree | b4cb3183bad5e68e5f0fa2b7833ab4ee149dad48 | |
parent | fcad5b298c7859d7f10908fab7b82983e286bb8d (diff) | |
download | bcm5719-llvm-5fe5c0a60f9a5f32da4316ba0d1732a1e439703b.tar.gz bcm5719-llvm-5fe5c0a60f9a5f32da4316ba0d1732a1e439703b.zip |
[X86] Preserve fpexcept property when turning strict_fp_extend and strict_fp_round into stack operations.
We use the stack for X87 fp_round and for moving from SSE f32/f64 to
X87 f64/f80. Or from X87 f64/f80 to SSE f32/f64.
Note for the SSE<->X87 conversions the conversion always happens in the
X87 domain. The load/store ops in the X87 instructions are able
to signal exceptions.
-rw-r--r-- | llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 38 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86InstrFPStack.td | 3 |
2 files changed, 37 insertions, 4 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 201082fac57..a621d7ed740 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -1128,10 +1128,40 @@ void X86DAGToDAGISel::PreprocessISelDAG() { // FIXME: optimize the case where the src/dest is a load or store? //Since the operation is StrictFP, use the preexisting chain. - SDValue Store = CurDAG->getTruncStore(N->getOperand(0), dl, N->getOperand(1), - MemTmp, MachinePointerInfo(), MemVT); - SDValue Result = CurDAG->getExtLoad(ISD::EXTLOAD, dl, DstVT, Store, MemTmp, - MachinePointerInfo(), MemVT); + SDValue Store, Result; + if (!SrcIsSSE) { + SDVTList VTs = CurDAG->getVTList(MVT::Other); + SDValue Ops[] = {N->getOperand(0), N->getOperand(1), MemTmp}; + Store = CurDAG->getMemIntrinsicNode(X86ISD::FST, dl, VTs, Ops, MemVT, + MachinePointerInfo(), 0, + MachineMemOperand::MOStore); + if (N->getFlags().hasNoFPExcept()) { + SDNodeFlags Flags = Store->getFlags(); + Flags.setNoFPExcept(true); + Store->setFlags(Flags); + } + } else { + assert(SrcVT == MemVT && "Unexpected VT!"); + Store = CurDAG->getStore(N->getOperand(0), dl, N->getOperand(1), MemTmp, + MachinePointerInfo()); + } + + if (!DstIsSSE) { + SDVTList VTs = CurDAG->getVTList(DstVT, MVT::Other); + SDValue Ops[] = {Store, MemTmp}; + Result = CurDAG->getMemIntrinsicNode(X86ISD::FLD, dl, VTs, Ops, MemVT, + MachinePointerInfo(), 0, + MachineMemOperand::MOLoad); + if (N->getFlags().hasNoFPExcept()) { + SDNodeFlags Flags = Result->getFlags(); + Flags.setNoFPExcept(true); + Result->setFlags(Flags); + } + } else { + assert(DstVT == MemVT && "Unexpected VT!"); + Result = + CurDAG->getLoad(DstVT, dl, Store, MemTmp, MachinePointerInfo()); + } // We're about to replace all uses of the FP_ROUND/FP_EXTEND with the // extload we created. This will cause general havok on the dag because diff --git a/llvm/lib/Target/X86/X86InstrFPStack.td b/llvm/lib/Target/X86/X86InstrFPStack.td index 1bd9ea47c2e..2cdf2ae15ce 100644 --- a/llvm/lib/Target/X86/X86InstrFPStack.td +++ b/llvm/lib/Target/X86/X86InstrFPStack.td @@ -777,7 +777,10 @@ def FXRSTOR64 : RI<0xAE, MRM1m, (outs), (ins opaquemem:$src), // Required for RET of f32 / f64 / f80 values. def : Pat<(X86fldf32 addr:$src), (LD_Fp32m addr:$src)>; +def : Pat<(X86fldf32 addr:$src), (LD_Fp32m64 addr:$src)>; def : Pat<(X86fldf64 addr:$src), (LD_Fp64m addr:$src)>; +def : Pat<(X86fldf32 addr:$src), (LD_Fp32m80 addr:$src)>; +def : Pat<(X86fldf64 addr:$src), (LD_Fp64m80 addr:$src)>; def : Pat<(X86fldf80 addr:$src), (LD_Fp80m addr:$src)>; // Required for CALL which return f32 / f64 / f80 values. |