Index: include/llvm/Target/TargetSelectionDAG.td =================================================================== --- include/llvm/Target/TargetSelectionDAG.td +++ include/llvm/Target/TargetSelectionDAG.td @@ -445,6 +445,35 @@ def f16_to_fp : SDNode<"ISD::FP16_TO_FP" , SDTIntToFPOp>; def fp_to_f16 : SDNode<"ISD::FP_TO_FP16" , SDTFPToIntOp>; +def strict_fadd : SDNode<"ISD::STRICT_FADD", + SDTFPBinOp, [SDNPHasChain, SDNPCommutative]>; +def strict_fsub : SDNode<"ISD::STRICT_FSUB", + SDTFPBinOp, [SDNPHasChain]>; +def strict_fmul : SDNode<"ISD::STRICT_FMUL", + SDTFPBinOp, [SDNPHasChain, SDNPCommutative]>; +def strict_fdiv : SDNode<"ISD::STRICT_FDIV", + SDTFPBinOp, [SDNPHasChain]>; +def strict_frem : SDNode<"ISD::STRICT_FREM", + SDTFPBinOp, [SDNPHasChain]>; +def strict_fma : SDNode<"ISD::STRICT_FMA", + SDTFPTernaryOp, [SDNPHasChain]>; +def strict_fsqrt : SDNode<"ISD::STRICT_FSQRT", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fsin : SDNode<"ISD::STRICT_FSIN", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fcos : SDNode<"ISD::STRICT_FCOS", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fexp2 : SDNode<"ISD::STRICT_FEXP2", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fpow : SDNode<"ISD::STRICT_FPOW", + SDTFPBinOp, [SDNPHasChain]>; +def strict_flog2 : SDNode<"ISD::STRICT_FLOG2", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_frint : SDNode<"ISD::STRICT_FRINT", + SDTFPUnaryOp, [SDNPHasChain]>; +def strict_fnearbyint : SDNode<"ISD::STRICT_FNEARBYINT", + SDTFPUnaryOp, [SDNPHasChain]>; + def setcc : SDNode<"ISD::SETCC" , SDTSetCC>; def select : SDNode<"ISD::SELECT" , SDTSelect>; def vselect : SDNode<"ISD::VSELECT" , SDTVSelect>; Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1084,7 +1084,9 @@ // node should be mutated. // // FIXME: The backends need a way to handle FP constraints. - if (Node->isStrictFPOpcode()) + if (Node->isStrictFPOpcode() && + (TLI->getOperationAction(Node->getOpcode(), Node->getValueType(0)) + != TargetLowering::Legal)) Node = CurDAG->mutateStrictFPToFP(Node); DEBUG(dbgs() << "\nISEL: Starting selection on root node: "; Index: lib/CodeGen/TargetLoweringBase.cpp =================================================================== --- lib/CodeGen/TargetLoweringBase.cpp +++ lib/CodeGen/TargetLoweringBase.cpp @@ -638,6 +638,26 @@ setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, VT, Expand); } + // Constrained floating-point operations default to expand. + setOperationAction(ISD::STRICT_FADD, VT, Expand); + setOperationAction(ISD::STRICT_FSUB, VT, Expand); + setOperationAction(ISD::STRICT_FMUL, VT, Expand); + setOperationAction(ISD::STRICT_FDIV, VT, Expand); + setOperationAction(ISD::STRICT_FREM, VT, Expand); + setOperationAction(ISD::STRICT_FMA, VT, Expand); + setOperationAction(ISD::STRICT_FSQRT, VT, Expand); + setOperationAction(ISD::STRICT_FPOW, VT, Expand); + setOperationAction(ISD::STRICT_FPOWI, VT, Expand); + setOperationAction(ISD::STRICT_FSIN, VT, Expand); + setOperationAction(ISD::STRICT_FCOS, VT, Expand); + setOperationAction(ISD::STRICT_FEXP, VT, Expand); + setOperationAction(ISD::STRICT_FEXP2, VT, Expand); + setOperationAction(ISD::STRICT_FLOG, VT, Expand); + setOperationAction(ISD::STRICT_FLOG10, VT, Expand); + setOperationAction(ISD::STRICT_FLOG2, VT, Expand); + setOperationAction(ISD::STRICT_FRINT, VT, Expand); + setOperationAction(ISD::STRICT_FNEARBYINT, VT, Expand); + // For most targets @llvm.get.dynamic.area.offset just returns 0. setOperationAction(ISD::GET_DYNAMIC_AREA_OFFSET, VT, Expand); } Index: lib/Target/SystemZ/SystemZISelLowering.cpp =================================================================== --- lib/Target/SystemZ/SystemZISelLowering.cpp +++ lib/Target/SystemZ/SystemZISelLowering.cpp @@ -387,6 +387,18 @@ setOperationAction(ISD::FSINCOS, VT, Expand); setOperationAction(ISD::FREM, VT, Expand); setOperationAction(ISD::FPOW, VT, Expand); + + // Handle constrained floating-point operations. + setOperationAction(ISD::STRICT_FADD, VT, Legal); + setOperationAction(ISD::STRICT_FSUB, VT, Legal); + setOperationAction(ISD::STRICT_FMUL, VT, Legal); + setOperationAction(ISD::STRICT_FDIV, VT, Legal); + setOperationAction(ISD::STRICT_FMA, VT, Legal); + setOperationAction(ISD::STRICT_FSQRT, VT, Legal); + setOperationAction(ISD::STRICT_FRINT, VT, Legal); + if (Subtarget.hasFPExtension()) { + setOperationAction(ISD::STRICT_FNEARBYINT, VT, Legal); + } } } Index: lib/Target/SystemZ/SystemZInstrFP.td =================================================================== --- lib/Target/SystemZ/SystemZInstrFP.td +++ lib/Target/SystemZ/SystemZInstrFP.td @@ -349,36 +349,42 @@ def LNDFR_32 : UnaryRRE<"lndfr", 0xB371, fnabs, FP32, FP32>; // Square root. -def SQEBR : UnaryRRE<"sqebr", 0xB314, fsqrt, FP32, FP32>; -def SQDBR : UnaryRRE<"sqdbr", 0xB315, fsqrt, FP64, FP64>; -def SQXBR : UnaryRRE<"sqxbr", 0xB316, fsqrt, FP128, FP128>; +defm SQEBR : FPUnaryRRE<"sqebr", 0xB314, fsqrt, strict_fsqrt, FP32, FP32>; +defm SQDBR : FPUnaryRRE<"sqdbr", 0xB315, fsqrt, strict_fsqrt, FP64, FP64>; +defm SQXBR : FPUnaryRRE<"sqxbr", 0xB316, fsqrt, strict_fsqrt, FP128, FP128>; -def SQEB : UnaryRXE<"sqeb", 0xED14, loadu, FP32, 4>; -def SQDB : UnaryRXE<"sqdb", 0xED15, loadu, FP64, 8>; +defm SQEB : FPUnaryRXE<"sqeb", 0xED14, loadu, loadu, FP32, 4>; +defm SQDB : FPUnaryRXE<"sqdb", 0xED15, loadu, loadu, FP64, 8>; // Round to an integer, with the second operand (modifier M3) specifying // the rounding mode. These forms always check for inexact conditions. -def FIEBR : BinaryRRFe<"fiebr", 0xB357, FP32, FP32>; -def FIDBR : BinaryRRFe<"fidbr", 0xB35F, FP64, FP64>; -def FIXBR : BinaryRRFe<"fixbr", 0xB347, FP128, FP128>; +defm FIEBR : FPBinaryRRFe<"fiebr", 0xB357, FP32, FP32>; +defm FIDBR : FPBinaryRRFe<"fidbr", 0xB35F, FP64, FP64>; +defm FIXBR : FPBinaryRRFe<"fixbr", 0xB347, FP128, FP128>; // frint rounds according to the current mode (modifier 0) and detects // inexact conditions. def : Pat<(frint FP32:$src), (FIEBR 0, FP32:$src)>; def : Pat<(frint FP64:$src), (FIDBR 0, FP64:$src)>; def : Pat<(frint FP128:$src), (FIXBR 0, FP128:$src)>; +def : Pat<(strict_frint FP32:$src), (FIEBRStrict 0, FP32:$src)>; +def : Pat<(strict_frint FP64:$src), (FIDBRStrict 0, FP64:$src)>; +def : Pat<(strict_frint FP128:$src), (FIXBRStrict 0, FP128:$src)>; let Predicates = [FeatureFPExtension] in { // Extended forms of the FIxBR instructions. M4 can be set to 4 // to suppress detection of inexact conditions. - def FIEBRA : TernaryRRFe<"fiebra", 0xB357, FP32, FP32>; - def FIDBRA : TernaryRRFe<"fidbra", 0xB35F, FP64, FP64>; - def FIXBRA : TernaryRRFe<"fixbra", 0xB347, FP128, FP128>; + defm FIEBRA : FPTernaryRRFe<"fiebra", 0xB357, FP32, FP32>; + defm FIDBRA : FPTernaryRRFe<"fidbra", 0xB35F, FP64, FP64>; + defm FIXBRA : FPTernaryRRFe<"fixbra", 0xB347, FP128, FP128>; // fnearbyint is like frint but does not detect inexact conditions. def : Pat<(fnearbyint FP32:$src), (FIEBRA 0, FP32:$src, 4)>; def : Pat<(fnearbyint FP64:$src), (FIDBRA 0, FP64:$src, 4)>; def : Pat<(fnearbyint FP128:$src), (FIXBRA 0, FP128:$src, 4)>; + def : Pat<(strict_fnearbyint FP32:$src), (FIEBRAStrict 0, FP32:$src, 4)>; + def : Pat<(strict_fnearbyint FP64:$src), (FIDBRAStrict 0, FP64:$src, 4)>; + def : Pat<(strict_fnearbyint FP128:$src), (FIXBRAStrict 0, FP128:$src, 4)>; // floor is no longer allowed to raise an inexact condition, // so restrict it to the cases where the condition can be suppressed. @@ -409,84 +415,104 @@ //===----------------------------------------------------------------------===// // Addition. -let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0xF in { +let CCValues = 0xF, CompareZeroCCMask = 0xF in { let isCommutable = 1 in { - def AEBR : BinaryRRE<"aebr", 0xB30A, fadd, FP32, FP32>; - def ADBR : BinaryRRE<"adbr", 0xB31A, fadd, FP64, FP64>; - def AXBR : BinaryRRE<"axbr", 0xB34A, fadd, FP128, FP128>; + defm AEBR : FPBinaryRRE<"aebr", 0xB30A, fadd, strict_fadd, FP32, FP32, [CC]>; + defm ADBR : FPBinaryRRE<"adbr", 0xB31A, fadd, strict_fadd, FP64, FP64, [CC]>; + defm AXBR : FPBinaryRRE<"axbr", 0xB34A, fadd, strict_fadd, FP128, FP128, [CC]>; } - def AEB : BinaryRXE<"aeb", 0xED0A, fadd, FP32, load, 4>; - def ADB : BinaryRXE<"adb", 0xED1A, fadd, FP64, load, 8>; + defm AEB : FPBinaryRXE<"aeb", 0xED0A, fadd, strict_fadd, FP32, load, 4, [CC]>; + defm ADB : FPBinaryRXE<"adb", 0xED1A, fadd, strict_fadd, FP64, load, 8, [CC]>; } // Subtraction. -let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0xF in { - def SEBR : BinaryRRE<"sebr", 0xB30B, fsub, FP32, FP32>; - def SDBR : BinaryRRE<"sdbr", 0xB31B, fsub, FP64, FP64>; - def SXBR : BinaryRRE<"sxbr", 0xB34B, fsub, FP128, FP128>; +let CCValues = 0xF, CompareZeroCCMask = 0xF in { + defm SEBR : FPBinaryRRE<"sebr", 0xB30B, fsub, strict_fsub, FP32, FP32, [CC]>; + defm SDBR : FPBinaryRRE<"sdbr", 0xB31B, fsub, strict_fsub, FP64, FP64, [CC]>; + defm SXBR : FPBinaryRRE<"sxbr", 0xB34B, fsub, strict_fsub, FP128, FP128, [CC]>; - def SEB : BinaryRXE<"seb", 0xED0B, fsub, FP32, load, 4>; - def SDB : BinaryRXE<"sdb", 0xED1B, fsub, FP64, load, 8>; + defm SEB : FPBinaryRXE<"seb", 0xED0B, fsub, strict_fsub, FP32, load, 4, [CC]>; + defm SDB : FPBinaryRXE<"sdb", 0xED1B, fsub, strict_fsub, FP64, load, 8, [CC]>; } // Multiplication. let isCommutable = 1 in { - def MEEBR : BinaryRRE<"meebr", 0xB317, fmul, FP32, FP32>; - def MDBR : BinaryRRE<"mdbr", 0xB31C, fmul, FP64, FP64>; - def MXBR : BinaryRRE<"mxbr", 0xB34C, fmul, FP128, FP128>; + defm MEEBR : FPBinaryRRE<"meebr", 0xB317, fmul, strict_fmul, FP32, FP32>; + defm MDBR : FPBinaryRRE<"mdbr", 0xB31C, fmul, strict_fmul, FP64, FP64>; + defm MXBR : FPBinaryRRE<"mxbr", 0xB34C, fmul, strict_fmul, FP128, FP128>; } -def MEEB : BinaryRXE<"meeb", 0xED17, fmul, FP32, load, 4>; -def MDB : BinaryRXE<"mdb", 0xED1C, fmul, FP64, load, 8>; +defm MEEB : FPBinaryRXE<"meeb", 0xED17, fmul, strict_fmul, FP32, load, 4>; +defm MDB : FPBinaryRXE<"mdb", 0xED1C, fmul, strict_fmul, FP64, load, 8>; // f64 multiplication of two FP32 registers. -def MDEBR : BinaryRRE<"mdebr", 0xB30C, null_frag, FP64, FP32>; +defm MDEBR : FPBinaryRRE<"mdebr", 0xB30C, null_frag, null_frag, FP64, FP32>; def : Pat<(fmul (f64 (fpextend FP32:$src1)), (f64 (fpextend FP32:$src2))), (MDEBR (INSERT_SUBREG (f64 (IMPLICIT_DEF)), FP32:$src1, subreg_r32), FP32:$src2)>; +def : Pat<(strict_fmul (f64 (fpextend FP32:$src1)), + (f64 (fpextend FP32:$src2))), + (MDEBRStrict (INSERT_SUBREG (f64 (IMPLICIT_DEF)), + FP32:$src1, subreg_r32), FP32:$src2)>; // f64 multiplication of an FP32 register and an f32 memory. -def MDEB : BinaryRXE<"mdeb", 0xED0C, null_frag, FP64, load, 4>; +defm MDEB : FPBinaryRXE<"mdeb", 0xED0C, null_frag, null_frag, FP64, load, 4>; def : Pat<(fmul (f64 (fpextend FP32:$src1)), (f64 (extloadf32 bdxaddr12only:$addr))), (MDEB (INSERT_SUBREG (f64 (IMPLICIT_DEF)), FP32:$src1, subreg_r32), bdxaddr12only:$addr)>; +def : Pat<(strict_fmul (f64 (fpextend FP32:$src1)), + (f64 (extloadf32 bdxaddr12only:$addr))), + (MDEBStrict (INSERT_SUBREG (f64 (IMPLICIT_DEF)), + FP32:$src1, subreg_r32), + bdxaddr12only:$addr)>; // f128 multiplication of two FP64 registers. -def MXDBR : BinaryRRE<"mxdbr", 0xB307, null_frag, FP128, FP64>; -let Predicates = [FeatureNoVectorEnhancements1] in +defm MXDBR : FPBinaryRRE<"mxdbr", 0xB307, null_frag, null_frag, FP128, FP64>; +let Predicates = [FeatureNoVectorEnhancements1] in { def : Pat<(fmul (f128 (fpextend FP64:$src1)), (f128 (fpextend FP64:$src2))), (MXDBR (INSERT_SUBREG (f128 (IMPLICIT_DEF)), FP64:$src1, subreg_h64), FP64:$src2)>; + def : Pat<(strict_fmul (f128 (fpextend FP64:$src1)), + (f128 (fpextend FP64:$src2))), + (MXDBRStrict (INSERT_SUBREG (f128 (IMPLICIT_DEF)), + FP64:$src1, subreg_h64), FP64:$src2)>; +} // f128 multiplication of an FP64 register and an f64 memory. -def MXDB : BinaryRXE<"mxdb", 0xED07, null_frag, FP128, load, 8>; -let Predicates = [FeatureNoVectorEnhancements1] in +defm MXDB : FPBinaryRXE<"mxdb", 0xED07, null_frag, null_frag, FP128, load, 8>; +let Predicates = [FeatureNoVectorEnhancements1] in { def : Pat<(fmul (f128 (fpextend FP64:$src1)), (f128 (extloadf64 bdxaddr12only:$addr))), (MXDB (INSERT_SUBREG (f128 (IMPLICIT_DEF)), FP64:$src1, subreg_h64), bdxaddr12only:$addr)>; + def : Pat<(strict_fmul (f128 (fpextend FP64:$src1)), + (f128 (extloadf64 bdxaddr12only:$addr))), + (MXDBStrict (INSERT_SUBREG (f128 (IMPLICIT_DEF)), + FP64:$src1, subreg_h64), + bdxaddr12only:$addr)>; +} // Fused multiply-add. -def MAEBR : TernaryRRD<"maebr", 0xB30E, z_fma, FP32, FP32>; -def MADBR : TernaryRRD<"madbr", 0xB31E, z_fma, FP64, FP64>; +defm MAEBR : FPTernaryRRD<"maebr", 0xB30E, z_fma, z_strict_fma, FP32, FP32>; +defm MADBR : FPTernaryRRD<"madbr", 0xB31E, z_fma, z_strict_fma, FP64, FP64>; -def MAEB : TernaryRXF<"maeb", 0xED0E, z_fma, FP32, FP32, load, 4>; -def MADB : TernaryRXF<"madb", 0xED1E, z_fma, FP64, FP64, load, 8>; +defm MAEB : FPTernaryRXF<"maeb", 0xED0E, z_fma, z_strict_fma, FP32, FP32, load, 4>; +defm MADB : FPTernaryRXF<"madb", 0xED1E, z_fma, z_strict_fma, FP64, FP64, load, 8>; // Fused multiply-subtract. -def MSEBR : TernaryRRD<"msebr", 0xB30F, z_fms, FP32, FP32>; -def MSDBR : TernaryRRD<"msdbr", 0xB31F, z_fms, FP64, FP64>; +defm MSEBR : FPTernaryRRD<"msebr", 0xB30F, z_fms, z_strict_fms, FP32, FP32>; +defm MSDBR : FPTernaryRRD<"msdbr", 0xB31F, z_fms, z_strict_fms, FP64, FP64>; -def MSEB : TernaryRXF<"mseb", 0xED0F, z_fms, FP32, FP32, load, 4>; -def MSDB : TernaryRXF<"msdb", 0xED1F, z_fms, FP64, FP64, load, 8>; +defm MSEB : FPTernaryRXF<"mseb", 0xED0F, z_fms, z_strict_fms, FP32, FP32, load, 4>; +defm MSDB : FPTernaryRXF<"msdb", 0xED1F, z_fms, z_strict_fms, FP64, FP64, load, 8>; // Division. -def DEBR : BinaryRRE<"debr", 0xB30D, fdiv, FP32, FP32>; -def DDBR : BinaryRRE<"ddbr", 0xB31D, fdiv, FP64, FP64>; -def DXBR : BinaryRRE<"dxbr", 0xB34D, fdiv, FP128, FP128>; +defm DEBR : FPBinaryRRE<"debr", 0xB30D, fdiv, strict_fdiv, FP32, FP32>; +defm DDBR : FPBinaryRRE<"ddbr", 0xB31D, fdiv, strict_fdiv, FP64, FP64>; +defm DXBR : FPBinaryRRE<"dxbr", 0xB34D, fdiv, strict_fdiv, FP128, FP128>; -def DEB : BinaryRXE<"deb", 0xED0D, fdiv, FP32, load, 4>; -def DDB : BinaryRXE<"ddb", 0xED1D, fdiv, FP64, load, 8>; +defm DEB : FPBinaryRXE<"deb", 0xED0D, fdiv, strict_fdiv, FP32, load, 4>; +defm DDB : FPBinaryRXE<"ddb", 0xED1D, fdiv, strict_fdiv, FP64, load, 8>; // Divide to integer. let Defs = [CC] in { Index: lib/Target/SystemZ/SystemZInstrFormats.td =================================================================== --- lib/Target/SystemZ/SystemZInstrFormats.td +++ lib/Target/SystemZ/SystemZInstrFormats.td @@ -2691,11 +2691,11 @@ } class UnaryRRE opcode, SDPatternOperator operator, - RegisterOperand cls1, RegisterOperand cls2> + RegisterOperand cls1, RegisterOperand cls2, string key = ""> : InstRRE { - let OpKey = mnemonic#cls1; + let OpKey = mnemonic#cls1#key; let OpType = "reg"; } @@ -2805,11 +2805,11 @@ } class UnaryRXE opcode, SDPatternOperator operator, - RegisterOperand cls, bits<5> bytes> + RegisterOperand cls, bits<5> bytes, string key = ""> : InstRXE { - let OpKey = mnemonic#"r"#cls; + let OpKey = mnemonic#"r"#cls#key; let OpType = "mem"; let mayLoad = 1; let AccessBytes = bytes; @@ -3041,11 +3041,11 @@ } class BinaryRRE opcode, SDPatternOperator operator, - RegisterOperand cls1, RegisterOperand cls2> + RegisterOperand cls1, RegisterOperand cls2, string key = ""> : InstRRE { - let OpKey = mnemonic#cls1; + let OpKey = mnemonic#cls1#key; let OpType = "reg"; let Constraints = "$R1 = $R1src"; let DisableEncoding = "$R1src"; @@ -3293,12 +3293,13 @@ } class BinaryRXE opcode, SDPatternOperator operator, - RegisterOperand cls, SDPatternOperator load, bits<5> bytes> + RegisterOperand cls, SDPatternOperator load, bits<5> bytes, + string key = ""> : InstRXE { - let OpKey = mnemonic#"r"#cls; + let OpKey = mnemonic#"r"#cls#key; let OpType = "mem"; let Constraints = "$R1 = $R1src"; let DisableEncoding = "$R1src"; @@ -4003,11 +4004,11 @@ mnemonic#"\t$R1, $M3, $R2, $M4", []>; class TernaryRRD opcode, SDPatternOperator operator, - RegisterOperand cls1, RegisterOperand cls2> + RegisterOperand cls1, RegisterOperand cls2, string key = ""> : InstRRD { - let OpKey = mnemonic#cls; + let OpKey = mnemonic#cls#key; let OpType = "reg"; let Constraints = "$R1 = $R1src"; let DisableEncoding = "$R1src"; @@ -4079,13 +4080,13 @@ class TernaryRXF opcode, SDPatternOperator operator, RegisterOperand cls1, RegisterOperand cls2, - SDPatternOperator load, bits<5> bytes> + SDPatternOperator load, bits<5> bytes, string key = ""> : InstRXF { - let OpKey = mnemonic#"r"#cls; + let OpKey = mnemonic#"r"#cls#key; let OpType = "mem"; let Constraints = "$R1 = $R1src"; let DisableEncoding = "$R1src"; @@ -4511,6 +4512,98 @@ def Compare : CompareRRE; } +// Multiclasses to create regular and constrained floating-point patterns. + +multiclass FPUnaryRRE opcode, + SDPatternOperator operator, SDPatternOperator strict_op, + RegisterOperand cls1, RegisterOperand cls2, + list CCDef = []> { + let isCodeGenOnly = 1, hasSideEffects = 1, + Uses = [FPC], Defs = !listconcat([FPC], CCDef) in + def Strict : UnaryRRE; + let Defs = CCDef in + def "" : UnaryRRE; +} + +multiclass FPUnaryRXE opcode, + SDPatternOperator operator, SDPatternOperator strict_op, + RegisterOperand cls, bits<5> bytes, + list CCDef = []> { + let isCodeGenOnly = 1, hasSideEffects = 1, + Uses = [FPC], Defs = !listconcat([FPC], CCDef) in + def Strict : UnaryRXE; + let Defs = CCDef in + def "" : UnaryRXE; +} + +multiclass FPBinaryRRE opcode, + SDPatternOperator operator, SDPatternOperator strict_op, + RegisterOperand cls1, RegisterOperand cls2, + list CCDef = []> { + let isCodeGenOnly = 1, hasSideEffects = 1, + Uses = [FPC], Defs = !listconcat([FPC], CCDef) in + def Strict : BinaryRRE; + let Defs = CCDef in + def "" : BinaryRRE; +} + +multiclass FPBinaryRXE opcode, + SDPatternOperator operator, SDPatternOperator strict_op, + RegisterOperand cls, SDPatternOperator load, + bits<5> bytes, list CCDef = []> { + let isCodeGenOnly = 1, hasSideEffects = 1, + Uses = [FPC], Defs = !listconcat([FPC], CCDef) in + def Strict : BinaryRXE; + let Defs = CCDef in + def "" : BinaryRXE; +} + +multiclass FPTernaryRRD opcode, + SDPatternOperator operator, SDPatternOperator strict_op, + RegisterOperand cls1, RegisterOperand cls2, + list CCDef = []> { + let isCodeGenOnly = 1, hasSideEffects = 1, + Uses = [FPC], Defs = !listconcat([FPC], CCDef) in + def Strict : TernaryRRD; + let Defs = CCDef in + def "" : TernaryRRD; +} + +multiclass FPTernaryRXF opcode, + SDPatternOperator operator, SDPatternOperator strict_op, + RegisterOperand cls1, RegisterOperand cls2, + SDPatternOperator load, bits<5> bytes, + list CCDef = []> { + let isCodeGenOnly = 1, hasSideEffects = 1, + Uses = [FPC], Defs = !listconcat([FPC], CCDef) in + def Strict : TernaryRXF; + let Defs = CCDef in + def "" : TernaryRXF; +} + + +multiclass FPBinaryRRFe opcode, + RegisterOperand cls1, RegisterOperand cls2, + list CCDef = []> { + let isCodeGenOnly = 1, hasSideEffects = 1, + Uses = [FPC], Defs = !listconcat([FPC], CCDef) in + def Strict : BinaryRRFe; + let Defs = CCDef in + def "" : BinaryRRFe; +} + +multiclass FPTernaryRRFe opcode, + RegisterOperand cls1, RegisterOperand cls2, + list CCDef = []> { + let isCodeGenOnly = 1, hasSideEffects = 1, + Uses = [FPC], Defs = !listconcat([FPC], CCDef) in + def Strict : TernaryRRFe; + let Defs = CCDef in + def "" : TernaryRRFe; +} + //===----------------------------------------------------------------------===// // Pseudo instructions //===----------------------------------------------------------------------===// Index: lib/Target/SystemZ/SystemZOperators.td =================================================================== --- lib/Target/SystemZ/SystemZOperators.td +++ lib/Target/SystemZ/SystemZOperators.td @@ -584,6 +584,10 @@ (fma node:$src2, node:$src3, node:$src1)>; def z_fms : PatFrag<(ops node:$src1, node:$src2, node:$src3), (fma node:$src2, node:$src3, (fneg node:$src1))>; +def z_strict_fma : PatFrag<(ops node:$src1, node:$src2, node:$src3), + (strict_fma node:$src2, node:$src3, node:$src1)>; +def z_strict_fms : PatFrag<(ops node:$src1, node:$src2, node:$src3), + (strict_fma node:$src2, node:$src3, (fneg node:$src1))>; // Negative fused multiply-add and multiply-subtract. def fnma : PatFrag<(ops node:$src1, node:$src2, node:$src3), Index: lib/Target/SystemZ/SystemZRegisterInfo.cpp =================================================================== --- lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -156,6 +156,9 @@ Reserved.set(SystemZ::A0); Reserved.set(SystemZ::A1); + // FPC is the floating-point status and control register. + Reserved.set(SystemZ::FPC); + return Reserved; } Index: lib/Target/SystemZ/SystemZRegisterInfo.td =================================================================== --- lib/Target/SystemZ/SystemZRegisterInfo.td +++ lib/Target/SystemZ/SystemZRegisterInfo.td @@ -299,6 +299,11 @@ let isAllocatable = 0 in def CCRegs : RegisterClass<"SystemZ", [i32], 32, (add CC)>; +// The floating-point control and status register. +def FPC : SystemZReg<"fpc">; +let isAllocatable = 0 in + def FPCRegs : RegisterClass<"SystemZ", [i32], 32, (add FPC)>; + // Access registers. class ACR32 num, string n> : SystemZReg { let HWEncoding = num; Index: lib/Target/SystemZ/SystemZScheduleZ13.td =================================================================== --- lib/Target/SystemZ/SystemZScheduleZ13.td +++ lib/Target/SystemZ/SystemZScheduleZ13.td @@ -830,46 +830,46 @@ def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "L(C|N|P)XBR$")>; // Square root -def : InstRW<[VecFPd, LSU], (instregex "SQ(E|D)B$")>; -def : InstRW<[VecFPd], (instregex "SQ(E|D)BR$")>; -def : InstRW<[VecFPd, VecFPd, GroupAlone], (instregex "SQXBR$")>; +def : InstRW<[VecFPd, LSU], (instregex "SQ(E|D)B(Strict)?$")>; +def : InstRW<[VecFPd], (instregex "SQ(E|D)BR(Strict)?$")>; +def : InstRW<[VecFPd, VecFPd, GroupAlone], (instregex "SQXBR(Strict)?$")>; // Load FP integer -def : InstRW<[VecBF], (instregex "FIEBR(A)?$")>; -def : InstRW<[VecBF], (instregex "FIDBR(A)?$")>; -def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "FIXBR(A)?$")>; +def : InstRW<[VecBF], (instregex "FIEBR(A)?(Strict)?$")>; +def : InstRW<[VecBF], (instregex "FIDBR(A)?(Strict)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "FIXBR(A)?(Strict)?$")>; //===----------------------------------------------------------------------===// // FP: Binary arithmetic //===----------------------------------------------------------------------===// // Addition -def : InstRW<[VecBF, LSU, Lat12], (instregex "A(E|D)B$")>; -def : InstRW<[VecBF], (instregex "A(E|D)BR$")>; -def : InstRW<[VecDF2, VecDF2, Lat10, GroupAlone], (instregex "AXBR$")>; +def : InstRW<[VecBF, LSU, Lat12], (instregex "A(E|D)B(Strict)?$")>; +def : InstRW<[VecBF], (instregex "A(E|D)BR(Strict)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat10, GroupAlone], (instregex "AXBR(Strict)?$")>; // Subtraction -def : InstRW<[VecBF, LSU, Lat12], (instregex "S(E|D)B$")>; -def : InstRW<[VecBF], (instregex "S(E|D)BR$")>; -def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "SXBR$")>; +def : InstRW<[VecBF, LSU, Lat12], (instregex "S(E|D)B(Strict)?$")>; +def : InstRW<[VecBF], (instregex "S(E|D)BR(Strict)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "SXBR(Strict)?$")>; // Multiply -def : InstRW<[VecBF, LSU, Lat12], (instregex "M(D|DE|EE)B$")>; -def : InstRW<[VecBF], (instregex "M(D|DE|EE)BR$")>; -def : InstRW<[VecBF2, VecBF2, LSU, Lat12, GroupAlone], (instregex "MXDB$")>; -def : InstRW<[VecBF2, VecBF2, GroupAlone], (instregex "MXDBR$")>; -def : InstRW<[VecDF2, VecDF2, Lat20, GroupAlone], (instregex "MXBR$")>; +def : InstRW<[VecBF, LSU, Lat12], (instregex "M(D|DE|EE)B(Strict)?$")>; +def : InstRW<[VecBF], (instregex "M(D|DE|EE)BR(Strict)?$")>; +def : InstRW<[VecBF2, VecBF2, LSU, Lat12, GroupAlone], (instregex "MXDB(Strict)?$")>; +def : InstRW<[VecBF2, VecBF2, GroupAlone], (instregex "MXDBR(Strict)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat20, GroupAlone], (instregex "MXBR(Strict)?$")>; // Multiply and add / subtract -def : InstRW<[VecBF2, LSU, Lat12, GroupAlone], (instregex "M(A|S)EB$")>; -def : InstRW<[VecBF, GroupAlone], (instregex "M(A|S)EBR$")>; -def : InstRW<[VecBF2, LSU, Lat12, GroupAlone], (instregex "M(A|S)DB$")>; -def : InstRW<[VecBF], (instregex "M(A|S)DBR$")>; +def : InstRW<[VecBF2, LSU, Lat12, GroupAlone], (instregex "M(A|S)EB(Strict)?$")>; +def : InstRW<[VecBF, GroupAlone], (instregex "M(A|S)EBR(Strict)?$")>; +def : InstRW<[VecBF2, LSU, Lat12, GroupAlone], (instregex "M(A|S)DB(Strict)?$")>; +def : InstRW<[VecBF], (instregex "M(A|S)DBR(Strict)?$")>; // Division -def : InstRW<[VecFPd, LSU], (instregex "D(E|D)B$")>; -def : InstRW<[VecFPd], (instregex "D(E|D)BR$")>; -def : InstRW<[VecFPd, VecFPd, GroupAlone], (instregex "DXBR$")>; +def : InstRW<[VecFPd, LSU], (instregex "D(E|D)B(Strict)?$")>; +def : InstRW<[VecFPd], (instregex "D(E|D)BR(Strict)?$")>; +def : InstRW<[VecFPd, VecFPd, GroupAlone], (instregex "DXBR(Strict)?$")>; // Divide to integer def : InstRW<[VecFPd, Lat30], (instregex "DI(E|D)BR$")>; Index: lib/Target/SystemZ/SystemZScheduleZ14.td =================================================================== --- lib/Target/SystemZ/SystemZScheduleZ14.td +++ lib/Target/SystemZ/SystemZScheduleZ14.td @@ -847,46 +847,46 @@ def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "L(C|N|P)XBR$")>; // Square root -def : InstRW<[VecFPd, LSU], (instregex "SQ(E|D)B$")>; -def : InstRW<[VecFPd], (instregex "SQ(E|D)BR$")>; -def : InstRW<[VecFPd, VecFPd, GroupAlone], (instregex "SQXBR$")>; +def : InstRW<[VecFPd, LSU], (instregex "SQ(E|D)B(Strict)?$")>; +def : InstRW<[VecFPd], (instregex "SQ(E|D)BR(Strict)?$")>; +def : InstRW<[VecFPd, VecFPd, GroupAlone], (instregex "SQXBR(Strict)?$")>; // Load FP integer -def : InstRW<[VecBF], (instregex "FIEBR(A)?$")>; -def : InstRW<[VecBF], (instregex "FIDBR(A)?$")>; -def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "FIXBR(A)?$")>; +def : InstRW<[VecBF], (instregex "FIEBR(A)?(Strict)?$")>; +def : InstRW<[VecBF], (instregex "FIDBR(A)?(Strict)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "FIXBR(A)?(Strict)?$")>; //===----------------------------------------------------------------------===// // FP: Binary arithmetic //===----------------------------------------------------------------------===// // Addition -def : InstRW<[VecBF, LSU, Lat12], (instregex "A(E|D)B$")>; -def : InstRW<[VecBF], (instregex "A(E|D)BR$")>; -def : InstRW<[VecDF2, VecDF2, Lat10, GroupAlone], (instregex "AXBR$")>; +def : InstRW<[VecBF, LSU, Lat12], (instregex "A(E|D)B(Strict)?$")>; +def : InstRW<[VecBF], (instregex "A(E|D)BR(Strict)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat10, GroupAlone], (instregex "AXBR(Strict)?$")>; // Subtraction -def : InstRW<[VecBF, LSU, Lat12], (instregex "S(E|D)B$")>; -def : InstRW<[VecBF], (instregex "S(E|D)BR$")>; -def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "SXBR$")>; +def : InstRW<[VecBF, LSU, Lat12], (instregex "S(E|D)B(Strict)?$")>; +def : InstRW<[VecBF], (instregex "S(E|D)BR(Strict)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat11, GroupAlone], (instregex "SXBR(Strict)?$")>; // Multiply -def : InstRW<[VecBF, LSU, Lat12], (instregex "M(D|DE|EE)B$")>; -def : InstRW<[VecBF], (instregex "M(D|DE|EE)BR$")>; -def : InstRW<[VecBF2, VecBF2, LSU, Lat12, GroupAlone], (instregex "MXDB$")>; -def : InstRW<[VecBF2, VecBF2, GroupAlone], (instregex "MXDBR$")>; -def : InstRW<[VecDF2, VecDF2, Lat20, GroupAlone], (instregex "MXBR$")>; +def : InstRW<[VecBF, LSU, Lat12], (instregex "M(D|DE|EE)B(Strict)?$")>; +def : InstRW<[VecBF], (instregex "M(D|DE|EE)BR(Strict)?$")>; +def : InstRW<[VecBF2, VecBF2, LSU, Lat12, GroupAlone], (instregex "MXDB(Strict)?$")>; +def : InstRW<[VecBF2, VecBF2, GroupAlone], (instregex "MXDBR(Strict)?$")>; +def : InstRW<[VecDF2, VecDF2, Lat20, GroupAlone], (instregex "MXBR(Strict)?$")>; // Multiply and add / subtract -def : InstRW<[VecBF2, LSU, Lat12, GroupAlone], (instregex "M(A|S)EB$")>; -def : InstRW<[VecBF, GroupAlone], (instregex "M(A|S)EBR$")>; -def : InstRW<[VecBF2, LSU, Lat12, GroupAlone], (instregex "M(A|S)DB$")>; -def : InstRW<[VecBF], (instregex "M(A|S)DBR$")>; +def : InstRW<[VecBF2, LSU, Lat12, GroupAlone], (instregex "M(A|S)EB(Strict)?$")>; +def : InstRW<[VecBF, GroupAlone], (instregex "M(A|S)EBR(Strict)?$")>; +def : InstRW<[VecBF2, LSU, Lat12, GroupAlone], (instregex "M(A|S)DB(Strict)?$")>; +def : InstRW<[VecBF], (instregex "M(A|S)DBR(Strict)?$")>; // Division -def : InstRW<[VecFPd, LSU], (instregex "D(E|D)B$")>; -def : InstRW<[VecFPd], (instregex "D(E|D)BR$")>; -def : InstRW<[VecFPd, VecFPd, GroupAlone], (instregex "DXBR$")>; +def : InstRW<[VecFPd, LSU], (instregex "D(E|D)B(Strict)?$")>; +def : InstRW<[VecFPd], (instregex "D(E|D)BR(Strict)?$")>; +def : InstRW<[VecFPd, VecFPd, GroupAlone], (instregex "DXBR(Strict)?$")>; // Divide to integer def : InstRW<[VecFPd, Lat30], (instregex "DI(E|D)BR$")>; Index: lib/Target/SystemZ/SystemZScheduleZ196.td =================================================================== --- lib/Target/SystemZ/SystemZScheduleZ196.td +++ lib/Target/SystemZ/SystemZScheduleZ196.td @@ -761,46 +761,46 @@ def : InstRW<[FPU2, FPU2, Lat9, GroupAlone], (instregex "L(C|N|P)XBR$")>; // Square root -def : InstRW<[FPU, LSU, Lat30], (instregex "SQ(E|D)B$")>; -def : InstRW<[FPU, Lat30], (instregex "SQ(E|D)BR$")>; -def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "SQXBR$")>; +def : InstRW<[FPU, LSU, Lat30], (instregex "SQ(E|D)B(Strict)?$")>; +def : InstRW<[FPU, Lat30], (instregex "SQ(E|D)BR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "SQXBR(Strict)?$")>; // Load FP integer -def : InstRW<[FPU], (instregex "FIEBR(A)?$")>; -def : InstRW<[FPU], (instregex "FIDBR(A)?$")>; -def : InstRW<[FPU2, FPU2, Lat15, GroupAlone], (instregex "FIXBR(A)?$")>; +def : InstRW<[FPU], (instregex "FIEBR(A)?(Strict)?$")>; +def : InstRW<[FPU], (instregex "FIDBR(A)?(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat15, GroupAlone], (instregex "FIXBR(A)?(Strict)?$")>; //===----------------------------------------------------------------------===// // FP: Binary arithmetic //===----------------------------------------------------------------------===// // Addition -def : InstRW<[FPU, LSU, Lat12], (instregex "A(E|D)B$")>; -def : InstRW<[FPU], (instregex "A(E|D)BR$")>; -def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "AXBR$")>; +def : InstRW<[FPU, LSU, Lat12], (instregex "A(E|D)B(Strict)?$")>; +def : InstRW<[FPU], (instregex "A(E|D)BR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "AXBR(Strict)?$")>; // Subtraction -def : InstRW<[FPU, LSU, Lat12], (instregex "S(E|D)B$")>; -def : InstRW<[FPU], (instregex "S(E|D)BR$")>; -def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "SXBR$")>; +def : InstRW<[FPU, LSU, Lat12], (instregex "S(E|D)B(Strict)?$")>; +def : InstRW<[FPU], (instregex "S(E|D)BR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "SXBR(Strict)?$")>; // Multiply -def : InstRW<[FPU, LSU, Lat12], (instregex "M(D|DE|EE)B$")>; -def : InstRW<[FPU], (instregex "M(D|DE|EE)BR$")>; -def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "MXDB$")>; -def : InstRW<[FPU2, FPU2, Lat10, GroupAlone], (instregex "MXDBR$")>; -def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "MXBR$")>; +def : InstRW<[FPU, LSU, Lat12], (instregex "M(D|DE|EE)B(Strict)?$")>; +def : InstRW<[FPU], (instregex "M(D|DE|EE)BR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "MXDB(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat10, GroupAlone], (instregex "MXDBR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "MXBR(Strict)?$")>; // Multiply and add / subtract -def : InstRW<[FPU, FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)EB$")>; -def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)EBR$")>; -def : InstRW<[FPU, FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)DB$")>; -def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)DBR$")>; +def : InstRW<[FPU, FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)EB(Strict)?$")>; +def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)EBR(Strict)?$")>; +def : InstRW<[FPU, FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)DB(Strict)?$")>; +def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)DBR(Strict)?$")>; // Division -def : InstRW<[FPU, LSU, Lat30], (instregex "D(E|D)B$")>; -def : InstRW<[FPU, Lat30], (instregex "D(E|D)BR$")>; -def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "DXBR$")>; +def : InstRW<[FPU, LSU, Lat30], (instregex "D(E|D)B(Strict)?$")>; +def : InstRW<[FPU, Lat30], (instregex "D(E|D)BR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "DXBR(Strict)?$")>; // Divide to integer def : InstRW<[FPU, Lat30], (instregex "DI(E|D)BR$")>; Index: lib/Target/SystemZ/SystemZScheduleZEC12.td =================================================================== --- lib/Target/SystemZ/SystemZScheduleZEC12.td +++ lib/Target/SystemZ/SystemZScheduleZEC12.td @@ -799,46 +799,46 @@ def : InstRW<[FPU2, FPU2, Lat9, GroupAlone], (instregex "L(C|N|P)XBR$")>; // Square root -def : InstRW<[FPU, LSU, Lat30], (instregex "SQ(E|D)B$")>; -def : InstRW<[FPU, Lat30], (instregex "SQ(E|D)BR$")>; -def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "SQXBR$")>; +def : InstRW<[FPU, LSU, Lat30], (instregex "SQ(E|D)B(Strict)?$")>; +def : InstRW<[FPU, Lat30], (instregex "SQ(E|D)BR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "SQXBR(Strict)?$")>; // Load FP integer -def : InstRW<[FPU], (instregex "FIEBR(A)?$")>; -def : InstRW<[FPU], (instregex "FIDBR(A)?$")>; -def : InstRW<[FPU2, FPU2, Lat15, GroupAlone], (instregex "FIXBR(A)?$")>; +def : InstRW<[FPU], (instregex "FIEBR(A)?(Strict)?$")>; +def : InstRW<[FPU], (instregex "FIDBR(A)?(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat15, GroupAlone], (instregex "FIXBR(A)?(Strict)?$")>; //===----------------------------------------------------------------------===// // FP: Binary arithmetic //===----------------------------------------------------------------------===// // Addition -def : InstRW<[FPU, LSU, Lat12], (instregex "A(E|D)B$")>; -def : InstRW<[FPU], (instregex "A(E|D)BR$")>; -def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "AXBR$")>; +def : InstRW<[FPU, LSU, Lat12], (instregex "A(E|D)B(Strict)?$")>; +def : InstRW<[FPU], (instregex "A(E|D)BR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "AXBR(Strict)?$")>; // Subtraction -def : InstRW<[FPU, LSU, Lat12], (instregex "S(E|D)B$")>; -def : InstRW<[FPU], (instregex "S(E|D)BR$")>; -def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "SXBR$")>; +def : InstRW<[FPU, LSU, Lat12], (instregex "S(E|D)B(Strict)?$")>; +def : InstRW<[FPU], (instregex "S(E|D)BR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat20, GroupAlone], (instregex "SXBR(Strict)?$")>; // Multiply -def : InstRW<[FPU, LSU, Lat12], (instregex "M(D|DE|EE)B$")>; -def : InstRW<[FPU], (instregex "M(D|DE|EE)BR$")>; -def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "MXDB$")>; -def : InstRW<[FPU2, FPU2, Lat10, GroupAlone], (instregex "MXDBR$")>; -def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "MXBR$")>; +def : InstRW<[FPU, LSU, Lat12], (instregex "M(D|DE|EE)B(Strict)?$")>; +def : InstRW<[FPU], (instregex "M(D|DE|EE)BR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, LSU, Lat15, GroupAlone], (instregex "MXDB(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat10, GroupAlone], (instregex "MXDBR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "MXBR(Strict)?$")>; // Multiply and add / subtract -def : InstRW<[FPU, FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)EB$")>; -def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)EBR$")>; -def : InstRW<[FPU, FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)DB$")>; -def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)DBR$")>; +def : InstRW<[FPU, FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)EB(Strict)?$")>; +def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)EBR(Strict)?$")>; +def : InstRW<[FPU, FPU, LSU, Lat12, GroupAlone], (instregex "M(A|S)DB(Strict)?$")>; +def : InstRW<[FPU, GroupAlone], (instregex "M(A|S)DBR(Strict)?$")>; // Division -def : InstRW<[FPU, LSU, Lat30], (instregex "D(E|D)B$")>; -def : InstRW<[FPU, Lat30], (instregex "D(E|D)BR$")>; -def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "DXBR$")>; +def : InstRW<[FPU, LSU, Lat30], (instregex "D(E|D)B(Strict)?$")>; +def : InstRW<[FPU, Lat30], (instregex "D(E|D)BR(Strict)?$")>; +def : InstRW<[FPU2, FPU2, Lat30, GroupAlone], (instregex "DXBR(Strict)?$")>; // Divide to integer def : InstRW<[FPU, Lat30], (instregex "DI(E|D)BR$")>;