Index: llvm/include/llvm/CodeGen/SelectionDAG.h =================================================================== --- llvm/include/llvm/CodeGen/SelectionDAG.h +++ llvm/include/llvm/CodeGen/SelectionDAG.h @@ -924,9 +924,9 @@ SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef Ops, const SDNodeFlags Flags = SDNodeFlags()); SDValue getNode(unsigned Opcode, const SDLoc &DL, ArrayRef ResultTys, - ArrayRef Ops); + ArrayRef Ops, const SDNodeFlags Flags = SDNodeFlags()); SDValue getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, - ArrayRef Ops); + ArrayRef Ops, const SDNodeFlags Flags = SDNodeFlags()); // Specialize based on number of operands. SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT); Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -2526,11 +2526,13 @@ // Okay, we found the operation and type to use. Zero extend our input to the // desired type then run the operation on it. if (IsStrict) { + SDNodeFlags Flags; + Flags.setFPExcept(N->getFlags().hasFPExcept()); SDValue Res = DAG.getNode(OpToUse, dl, {DestVT, MVT::Other}, {N->getOperand(0), DAG.getNode(IsSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND, - dl, NewInTy, LegalOp)}); + dl, NewInTy, LegalOp)}, Flags); Results.push_back(Res); Results.push_back(Res.getValue(1)); return; @@ -2581,8 +2583,10 @@ // Okay, we found the operation and type to use. SDValue Operation; if (IsStrict) { - SDVTList VTs = DAG.getVTList(NewOutTy, MVT::Other); - Operation = DAG.getNode(OpToUse, dl, VTs, N->getOperand(0), LegalOp); + SDNodeFlags Flags; + Flags.setFPExcept(N->getFlags().hasFPExcept()); + Operation = DAG.getNode(OpToUse, dl, { NewOutTy, MVT::Other }, + { N->getOperand(0), LegalOp }, Flags); } else Operation = DAG.getNode(OpToUse, dl, NewOutTy, LegalOp); Index: llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -219,7 +219,8 @@ Opers[i] = Oper; } - SDValue Result = DAG.getNode(N->getOpcode(), dl, ValueVTs, Opers); + SDValue Result = DAG.getNode(N->getOpcode(), dl, ValueVTs, Opers, + N->getFlags()); // Legalize the chain result - switch anything that used the old chain to // use the new one. @@ -1285,10 +1286,11 @@ OpsHi[i] = OpHi; } + const SDNodeFlags Flags = N->getFlags(); EVT LoValueVTs[] = {LoVT, MVT::Other}; EVT HiValueVTs[] = {HiVT, MVT::Other}; - Lo = DAG.getNode(N->getOpcode(), dl, LoValueVTs, OpsLo); - Hi = DAG.getNode(N->getOpcode(), dl, HiValueVTs, OpsHi); + Lo = DAG.getNode(N->getOpcode(), dl, LoValueVTs, OpsLo, Flags); + Hi = DAG.getNode(N->getOpcode(), dl, HiValueVTs, OpsHi, Flags); // Build a factor node to remember that this Op is independent of the // other one. @@ -3142,7 +3144,7 @@ } EVT WidenVT[] = {WidenEltVT, MVT::Other}; - SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps); + SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps, N->getFlags()); ConcatOps[ConcatEnd++] = Oper; Chains.push_back(Oper.getValue(1)); } Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -7350,14 +7350,15 @@ } SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, - ArrayRef ResultTys, ArrayRef Ops) { - return getNode(Opcode, DL, getVTList(ResultTys), Ops); + ArrayRef ResultTys, ArrayRef Ops, + const SDNodeFlags Flags) { + return getNode(Opcode, DL, getVTList(ResultTys), Ops, Flags); } SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList, - ArrayRef Ops) { + ArrayRef Ops, const SDNodeFlags Flags) { if (VTList.NumVTs == 1) - return getNode(Opcode, DL, VTList.VTs[0], Ops); + return getNode(Opcode, DL, VTList.VTs[0], Ops, Flags); switch (Opcode) { case ISD::STRICT_FP_EXTEND: @@ -7420,10 +7421,13 @@ FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTList, Ops); void *IP = nullptr; - if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) + if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) { + E->intersectFlagsWith(Flags); return SDValue(E, 0); + } N = newSDNode(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTList); + N->setFlags(Flags); createOperands(N, Ops); CSEMap.InsertNode(N, IP); } else { Index: llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -6065,8 +6065,10 @@ if (APFloat::opOverflow & APF.convertFromAPInt(SignMask, false, APFloat::rmNearestTiesToEven)) { if (Node->isStrictFPOpcode()) { + SDNodeFlags Flags; + Flags.setFPExcept(Node->getFlags().hasFPExcept()); Result = DAG.getNode(ISD::STRICT_FP_TO_SINT, dl, { DstVT, MVT::Other }, - { Node->getOperand(0), Src }); + { Node->getOperand(0), Src }, Flags); Chain = Result.getValue(1); } else Result = DAG.getNode(ISD::FP_TO_SINT, dl, DstVT, Src); @@ -6074,6 +6076,7 @@ } SDValue Cst = DAG.getConstantFP(APF, dl, SrcVT); + // FIXME: Does this need to be a strict comparision? SDValue Sel = DAG.getSetCC(dl, SetCCVT, Src, Cst, ISD::SETLT); bool Strict = Node->isStrictFPOpcode() || @@ -6095,10 +6098,12 @@ DAG.getConstant(SignMask, dl, DstVT)); SDValue SInt; if (Node->isStrictFPOpcode()) { + SDNodeFlags Flags; + Flags.setFPExcept(Node->getFlags().hasFPExcept()); SDValue Val = DAG.getNode(ISD::STRICT_FSUB, dl, { SrcVT, MVT::Other }, - { Node->getOperand(0), Src, FltOfs }); + { Node->getOperand(0), Src, FltOfs }, Flags); SInt = DAG.getNode(ISD::STRICT_FP_TO_SINT, dl, { DstVT, MVT::Other }, - { Val.getValue(1), Val }); + { Val.getValue(1), Val }, Flags); Chain = SInt.getValue(1); } else { SDValue Val = DAG.getNode(ISD::FSUB, dl, SrcVT, Src, FltOfs); Index: llvm/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.cpp +++ llvm/lib/Target/X86/X86ISelLowering.cpp @@ -18592,9 +18592,12 @@ // SSE doesn't have an i16 conversion so we need to promote. if (SrcVT == MVT::i16 && (UseSSEReg || VT == MVT::f128)) { SDValue Ext = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::i32, Src); - if (IsStrict) + if (IsStrict) { + SDNodeFlags Flags; + Flags.setFPExcept(Op->getFlags().hasFPExcept()); return DAG.getNode(ISD::STRICT_SINT_TO_FP, dl, {VT, MVT::Other}, - {Op.getOperand(0), Ext}); + {Op.getOperand(0), Ext}, Flags); + } return DAG.getNode(ISD::SINT_TO_FP, dl, VT, Ext); } @@ -19199,6 +19202,7 @@ SDValue ThreshVal = DAG.getConstantFP(Thresh, DL, TheVT); + // FIXME: Does this need to be a strict compare? SDValue Cmp = DAG.getSetCC(DL, getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), TheVT), @@ -19212,8 +19216,10 @@ ThreshVal); if (IsStrict) { + SDNodeFlags Flags; + Flags.setFPExcept(Op->getFlags().hasFPExcept()); Value = DAG.getNode(ISD::STRICT_FSUB, DL, { TheVT, MVT::Other}, - { Chain, Value, FltOfs }); + { Chain, Value, FltOfs }, Flags); Chain = Value.getValue(1); } else Value = DAG.getNode(ISD::FSUB, DL, TheVT, Value, FltOfs); @@ -19241,6 +19247,7 @@ MachineMemOperand *MMO = MF.getMachineMemOperand( MPI, MachineMemOperand::MOStore, MemSize, MemSize); SDValue Ops[] = { Chain, Value, StackSlot }; + // FIXME: How do we get the fpexcept flag onto this node? SDValue FIST = DAG.getMemIntrinsicNode(X86ISD::FP_TO_INT_IN_MEM, DL, DAG.getVTList(MVT::Other), Ops, DstTy, MMO); @@ -19831,8 +19838,10 @@ if (Subtarget.is64Bit()) { SDValue Res, Chain; if (IsStrict) { + SDNodeFlags Flags; + Flags.setFPExcept(Op->getFlags().hasFPExcept()); Res = DAG.getNode(ISD::STRICT_FP_TO_SINT, dl, { MVT::i64, MVT::Other}, - { Op.getOperand(0), Src }); + { Op.getOperand(0), Src }, Flags); Chain = Res.getValue(1); } else Res = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i64, Src); @@ -19856,8 +19865,10 @@ assert(IsSigned && "Expected i16 FP_TO_UINT to have been promoted!"); SDValue Res, Chain; if (IsStrict) { + SDNodeFlags Flags; + Flags.setFPExcept(Op->getFlags().hasFPExcept()); Res = DAG.getNode(ISD::STRICT_FP_TO_SINT, dl, { MVT::i32, MVT::Other}, - { Op.getOperand(0), Src }); + { Op.getOperand(0), Src }, Flags); Chain = Res.getValue(1); } else Res = DAG.getNode(ISD::FP_TO_SINT, dl, MVT::i32, Src); Index: llvm/test/CodeGen/X86/fp-intrinsics-flags-x86_64.ll =================================================================== --- llvm/test/CodeGen/X86/fp-intrinsics-flags-x86_64.ll +++ llvm/test/CodeGen/X86/fp-intrinsics-flags-x86_64.ll @@ -4,7 +4,7 @@ ; CHECK-LABEL: name: f20u ; CHECK: liveins: $xmm0 ; CHECK: [[COPY:%[0-9]+]]:fr64 = COPY $xmm0 -; CHECK: [[CVTTSD2SI64rr:%[0-9]+]]:gr64 = CVTTSD2SI64rr [[COPY]], implicit $mxcsr +; CHECK: [[CVTTSD2SI64rr:%[0-9]+]]:gr64 = fpexcept CVTTSD2SI64rr [[COPY]], implicit $mxcsr ; CHECK: [[COPY1:%[0-9]+]]:gr32 = COPY [[CVTTSD2SI64rr]].sub_32bit ; CHECK: $eax = COPY [[COPY1]] ; CHECK: RET 0, $eax Index: llvm/test/CodeGen/X86/fp-intrinsics-flags.ll =================================================================== --- llvm/test/CodeGen/X86/fp-intrinsics-flags.ll +++ llvm/test/CodeGen/X86/fp-intrinsics-flags.ll @@ -4,7 +4,7 @@ entry: ; CHECK-LABEL: name: sifdb ; CHECK: [[MOVSX32rm8_:%[0-9]+]]:gr32 = MOVSX32rm8 %fixed-stack.0, 1, $noreg, 0, $noreg :: (load 1 from %fixed-stack.0, align 16) -; CHECK: [[CVTSI2SDrr:%[0-9]+]]:fr64 = CVTSI2SDrr killed [[MOVSX32rm8_]] +; CHECK: [[CVTSI2SDrr:%[0-9]+]]:fr64 = fpexcept CVTSI2SDrr killed [[MOVSX32rm8_]] ; CHECK: MOVSDmr %stack.0, 1, $noreg, 0, $noreg, killed [[CVTSI2SDrr]] :: (store 8 into %stack.0, align 4) ; CHECK: [[LD_Fp64m80_:%[0-9]+]]:rfp80 = LD_Fp64m80 %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load 8 from %stack.0, align 4) ; CHECK: RET 0, killed [[LD_Fp64m80_]] @@ -16,7 +16,7 @@ entry: ; CHECK-LABEL: name: sifdw ; CHECK: [[MOVSX32rm16_:%[0-9]+]]:gr32 = MOVSX32rm16 %fixed-stack.0, 1, $noreg, 0, $noreg :: (load 2 from %fixed-stack.0, align 16) -; CHECK: [[CVTSI2SDrr:%[0-9]+]]:fr64 = CVTSI2SDrr killed [[MOVSX32rm16_]] +; CHECK: [[CVTSI2SDrr:%[0-9]+]]:fr64 = fpexcept CVTSI2SDrr killed [[MOVSX32rm16_]] ; CHECK: MOVSDmr %stack.0, 1, $noreg, 0, $noreg, killed [[CVTSI2SDrr]] :: (store 8 into %stack.0, align 4) ; CHECK: [[LD_Fp64m80_:%[0-9]+]]:rfp80 = LD_Fp64m80 %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load 8 from %stack.0, align 4) ; CHECK: RET 0, killed [[LD_Fp64m80_]] @@ -34,7 +34,7 @@ ; CHECK: [[COPY1:%[0-9]+]]:vr128 = COPY [[MOVSDrm_alt1]] ; CHECK: [[PANDNrr:%[0-9]+]]:vr128 = PANDNrr [[COPY]], killed [[COPY1]] ; CHECK: [[COPY2:%[0-9]+]]:fr64 = COPY [[PANDNrr]] -; CHECK: [[SUBSDrr:%[0-9]+]]:fr64 = SUBSDrr [[MOVSDrm_alt]], killed [[COPY2]], implicit $mxcsr +; CHECK: [[SUBSDrr:%[0-9]+]]:fr64 = fpexcept SUBSDrr [[MOVSDrm_alt]], killed [[COPY2]], implicit $mxcsr ; CHECK: MOVSDmr %stack.0, 1, $noreg, 0, $noreg, killed [[SUBSDrr]] :: (store 8 into %stack.0) ; CHECK: [[LD_Fp64m:%[0-9]+]]:rfp64 = LD_Fp64m %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load 8 from %stack.0) ; CHECK: FNSTCW16m %stack.1, 1, $noreg, 0, $noreg, implicit-def $fpsw, implicit $fpcw :: (store 2 into %stack.1) @@ -61,7 +61,7 @@ define i8 @f20s8(double %x) #0 { entry: ; CHECK-LABEL: name: f20s8 -; CHECK: [[CVTTSD2SIrm:%[0-9]+]]:gr32 = CVTTSD2SIrm %fixed-stack.0, 1, $noreg, 0, $noreg, implicit $mxcsr :: (load 8 from %fixed-stack.0, align 16) +; CHECK: [[CVTTSD2SIrm:%[0-9]+]]:gr32 = fpexcept CVTTSD2SIrm %fixed-stack.0, 1, $noreg, 0, $noreg, implicit $mxcsr :: (load 8 from %fixed-stack.0, align 16) ; CHECK: [[COPY:%[0-9]+]]:gr32_abcd = COPY [[CVTTSD2SIrm]] ; CHECK: [[COPY1:%[0-9]+]]:gr8 = COPY [[COPY]].sub_8bit ; CHECK: $al = COPY [[COPY1]] @@ -73,7 +73,7 @@ define i16 @f20s16(double %x) #0 { entry: ; CHECK-LABEL: name: f20s16 -; CHECK: [[CVTTSD2SIrm:%[0-9]+]]:gr32 = CVTTSD2SIrm %fixed-stack.0, 1, $noreg, 0, $noreg, implicit $mxcsr :: (load 8 from %fixed-stack.0, align 16) +; CHECK: [[CVTTSD2SIrm:%[0-9]+]]:gr32 = fpexcept CVTTSD2SIrm %fixed-stack.0, 1, $noreg, 0, $noreg, implicit $mxcsr :: (load 8 from %fixed-stack.0, align 16) ; CHECK: [[COPY:%[0-9]+]]:gr16 = COPY [[CVTTSD2SIrm]].sub_16bit ; CHECK: $ax = COPY [[COPY]] ; CHECK: RET 0, $ax @@ -95,8 +95,8 @@ ; CHECK: [[COPY1:%[0-9]+]]:vr128 = COPY [[MOVSDrm_alt1]] ; CHECK: [[PANDNrr:%[0-9]+]]:vr128 = PANDNrr [[COPY]], killed [[COPY1]] ; CHECK: [[COPY2:%[0-9]+]]:fr64 = COPY [[PANDNrr]] -; CHECK: [[SUBSDrr:%[0-9]+]]:fr64 = SUBSDrr [[MOVSDrm_alt]], killed [[COPY2]], implicit $mxcsr -; CHECK: [[CVTTSD2SIrr:%[0-9]+]]:gr32 = CVTTSD2SIrr killed [[SUBSDrr]], implicit $mxcsr +; CHECK: [[SUBSDrr:%[0-9]+]]:fr64 = fpexcept SUBSDrr [[MOVSDrm_alt]], killed [[COPY2]], implicit $mxcsr +; CHECK: [[CVTTSD2SIrr:%[0-9]+]]:gr32 = fpexcept CVTTSD2SIrr killed [[SUBSDrr]], implicit $mxcsr ; CHECK: [[XOR32rr:%[0-9]+]]:gr32 = XOR32rr [[CVTTSD2SIrr]], killed [[SHL32ri]], implicit-def dead $eflags ; CHECK: $eax = COPY [[XOR32rr]] ; CHECK: RET 0, $eax Index: llvm/test/CodeGen/X86/vector-constrained-fp-intrinsics-flags.ll =================================================================== --- llvm/test/CodeGen/X86/vector-constrained-fp-intrinsics-flags.ll +++ llvm/test/CodeGen/X86/vector-constrained-fp-intrinsics-flags.ll @@ -3,7 +3,7 @@ define <1 x float> @constrained_vector_fadd_v1f32() #0 { ; CHECK-LABEL: name: constrained_vector_fadd_v1f32 ; CHECK: [[MOVSSrm_alt:%[0-9]+]]:fr32 = MOVSSrm_alt $rip, 1, $noreg, %const.0, $noreg :: (load 4 from constant-pool) -; CHECK: [[ADDSSrm:%[0-9]+]]:fr32 = ADDSSrm [[MOVSSrm_alt]], $rip, 1, $noreg, %const.1, $noreg, implicit $mxcsr :: (load 4 from constant-pool) +; CHECK: [[ADDSSrm:%[0-9]+]]:fr32 = fpexcept ADDSSrm [[MOVSSrm_alt]], $rip, 1, $noreg, %const.1, $noreg, implicit $mxcsr :: (load 4 from constant-pool) ; CHECK: $xmm0 = COPY [[ADDSSrm]] ; CHECK: RET 0, $xmm0 entry: @@ -15,9 +15,9 @@ ; CHECK-LABEL: name: constrained_vector_fadd_v3f32 ; CHECK: [[FsFLD0SS:%[0-9]+]]:fr32 = FsFLD0SS ; CHECK: [[MOVSSrm_alt:%[0-9]+]]:fr32 = MOVSSrm_alt $rip, 1, $noreg, %const.0, $noreg :: (load 4 from constant-pool) -; CHECK: [[ADDSSrr:%[0-9]+]]:fr32 = ADDSSrr [[MOVSSrm_alt]], killed [[FsFLD0SS]], implicit $mxcsr -; CHECK: [[ADDSSrm:%[0-9]+]]:fr32 = ADDSSrm [[MOVSSrm_alt]], $rip, 1, $noreg, %const.1, $noreg, implicit $mxcsr :: (load 4 from constant-pool) -; CHECK: [[ADDSSrm1:%[0-9]+]]:fr32 = ADDSSrm [[MOVSSrm_alt]], $rip, 1, $noreg, %const.2, $noreg, implicit $mxcsr :: (load 4 from constant-pool) +; CHECK: [[ADDSSrr:%[0-9]+]]:fr32 = fpexcept ADDSSrr [[MOVSSrm_alt]], killed [[FsFLD0SS]], implicit $mxcsr +; CHECK: [[ADDSSrm:%[0-9]+]]:fr32 = fpexcept ADDSSrm [[MOVSSrm_alt]], $rip, 1, $noreg, %const.1, $noreg, implicit $mxcsr :: (load 4 from constant-pool) +; CHECK: [[ADDSSrm1:%[0-9]+]]:fr32 = fpexcept ADDSSrm [[MOVSSrm_alt]], $rip, 1, $noreg, %const.2, $noreg, implicit $mxcsr :: (load 4 from constant-pool) ; CHECK: [[COPY:%[0-9]+]]:vr128 = COPY [[ADDSSrm1]] ; CHECK: [[COPY1:%[0-9]+]]:vr128 = COPY [[ADDSSrm]] ; CHECK: [[UNPCKLPSrr:%[0-9]+]]:vr128 = UNPCKLPSrr [[COPY1]], killed [[COPY]] @@ -38,8 +38,8 @@ define <4 x double> @constrained_vector_fadd_v4f64() #0 { ; CHECK-LABEL: name: constrained_vector_fadd_v4f64 ; CHECK: [[MOVAPDrm:%[0-9]+]]:vr128 = MOVAPDrm $rip, 1, $noreg, %const.0, $noreg :: (load 16 from constant-pool) -; CHECK: [[ADDPDrm:%[0-9]+]]:vr128 = ADDPDrm [[MOVAPDrm]], $rip, 1, $noreg, %const.1, $noreg, implicit $mxcsr :: (load 16 from constant-pool) -; CHECK: [[ADDPDrm1:%[0-9]+]]:vr128 = ADDPDrm [[MOVAPDrm]], $rip, 1, $noreg, %const.2, $noreg, implicit $mxcsr :: (load 16 from constant-pool) +; CHECK: [[ADDPDrm:%[0-9]+]]:vr128 = fpexcept ADDPDrm [[MOVAPDrm]], $rip, 1, $noreg, %const.1, $noreg, implicit $mxcsr :: (load 16 from constant-pool) +; CHECK: [[ADDPDrm1:%[0-9]+]]:vr128 = fpexcept ADDPDrm [[MOVAPDrm]], $rip, 1, $noreg, %const.2, $noreg, implicit $mxcsr :: (load 16 from constant-pool) ; CHECK: $xmm0 = COPY [[ADDPDrm]] ; CHECK: $xmm1 = COPY [[ADDPDrm1]] ; CHECK: RET 0, $xmm0, $xmm1