Index: include/llvm/Target/TargetSelectionDAG.td =================================================================== --- include/llvm/Target/TargetSelectionDAG.td +++ include/llvm/Target/TargetSelectionDAG.td @@ -302,6 +302,7 @@ def implicit; def node; def srcvalue; +def alternative; def imm : SDNode<"ISD::Constant" , SDTIntLeaf , [], "ConstantSDNode">; def timm : SDNode<"ISD::TargetConstant",SDTIntLeaf, [], "ConstantSDNode">; Index: lib/Target/SystemZ/SystemZInstrInfo.td =================================================================== --- lib/Target/SystemZ/SystemZInstrInfo.td +++ lib/Target/SystemZ/SystemZInstrInfo.td @@ -895,8 +895,8 @@ let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0x8 in { // Addition of a register. let isCommutable = 1 in { - defm AR : BinaryRRAndK<"ar", 0x1A, 0xB9F8, z_saddo, GR32, GR32>; - defm AGR : BinaryRREAndK<"agr", 0xB908, 0xB9E8, z_saddo, GR64, GR64>; + defm AR : BinaryRRAndK<"ar", 0x1A, 0xB9F8, z_sadd, GR32, GR32>; + defm AGR : BinaryRREAndK<"agr", 0xB908, 0xB9E8, z_sadd, GR64, GR64>; } def AGFR : BinaryRRE<"agfr", 0xB918, null_frag, GR64, GR32>; @@ -907,38 +907,38 @@ Requires<[FeatureHighWord]>; // Addition of signed 16-bit immediates. - defm AHIMux : BinaryRIAndKPseudo<"ahimux", z_saddo, GRX32, imm32sx16>; - defm AHI : BinaryRIAndK<"ahi", 0xA7A, 0xECD8, z_saddo, GR32, imm32sx16>; - defm AGHI : BinaryRIAndK<"aghi", 0xA7B, 0xECD9, z_saddo, GR64, imm64sx16>; + defm AHIMux : BinaryRIAndKPseudo<"ahimux", z_sadd, GRX32, imm32sx16>; + defm AHI : BinaryRIAndK<"ahi", 0xA7A, 0xECD8, z_sadd, GR32, imm32sx16>; + defm AGHI : BinaryRIAndK<"aghi", 0xA7B, 0xECD9, z_sadd, GR64, imm64sx16>; // Addition of signed 32-bit immediates. - def AFIMux : BinaryRIPseudo, + def AFIMux : BinaryRIPseudo, Requires<[FeatureHighWord]>; - def AFI : BinaryRIL<"afi", 0xC29, z_saddo, GR32, simm32>; - def AIH : BinaryRIL<"aih", 0xCC8, z_saddo, GRH32, simm32>, + def AFI : BinaryRIL<"afi", 0xC29, z_sadd, GR32, simm32>; + def AIH : BinaryRIL<"aih", 0xCC8, z_sadd, GRH32, simm32>, Requires<[FeatureHighWord]>; - def AGFI : BinaryRIL<"agfi", 0xC28, z_saddo, GR64, imm64sx32>; + def AGFI : BinaryRIL<"agfi", 0xC28, z_sadd, GR64, imm64sx32>; // Addition of memory. - defm AH : BinaryRXPair<"ah", 0x4A, 0xE37A, z_saddo, GR32, asextloadi16, 2>; - defm A : BinaryRXPair<"a", 0x5A, 0xE35A, z_saddo, GR32, load, 4>; - def AGH : BinaryRXY<"agh", 0xE338, z_saddo, GR64, asextloadi16, 2>, + defm AH : BinaryRXPair<"ah", 0x4A, 0xE37A, z_sadd, GR32, asextloadi16, 2>; + defm A : BinaryRXPair<"a", 0x5A, 0xE35A, z_sadd, GR32, load, 4>; + def AGH : BinaryRXY<"agh", 0xE338, z_sadd, GR64, asextloadi16, 2>, Requires<[FeatureMiscellaneousExtensions2]>; - def AGF : BinaryRXY<"agf", 0xE318, z_saddo, GR64, asextloadi32, 4>; - def AG : BinaryRXY<"ag", 0xE308, z_saddo, GR64, load, 8>; + def AGF : BinaryRXY<"agf", 0xE318, z_sadd, GR64, asextloadi32, 4>; + def AG : BinaryRXY<"ag", 0xE308, z_sadd, GR64, load, 8>; // Addition to memory. - def ASI : BinarySIY<"asi", 0xEB6A, null_frag, imm32sx8>; - def AGSI : BinarySIY<"agsi", 0xEB7A, null_frag, imm64sx8>; + def ASI : BinarySIY<"asi", 0xEB6A, add, imm32sx8>; + def AGSI : BinarySIY<"agsi", 0xEB7A, add, imm64sx8>; } -defm : SXB; +defm : SXB; // Addition producing a carry. let Defs = [CC] in { // Addition of a register. let isCommutable = 1 in { - defm ALR : BinaryRRAndK<"alr", 0x1E, 0xB9FA, z_uaddo, GR32, GR32>; - defm ALGR : BinaryRREAndK<"algr", 0xB90A, 0xB9EA, z_uaddo, GR64, GR64>; + defm ALR : BinaryRRAndK<"alr", 0x1E, 0xB9FA, z_uadd, GR32, GR32>; + defm ALGR : BinaryRREAndK<"algr", 0xB90A, 0xB9EA, z_uadd, GR64, GR64>; } def ALGFR : BinaryRRE<"algfr", 0xB91A, null_frag, GR64, GR32>; @@ -949,29 +949,29 @@ Requires<[FeatureHighWord]>; // Addition of signed 16-bit immediates. - def ALHSIK : BinaryRIE<"alhsik", 0xECDA, z_uaddo, GR32, imm32sx16>, + def ALHSIK : BinaryRIE<"alhsik", 0xECDA, z_uadd, GR32, imm32sx16>, Requires<[FeatureDistinctOps]>; - def ALGHSIK : BinaryRIE<"alghsik", 0xECDB, z_uaddo, GR64, imm64sx16>, + def ALGHSIK : BinaryRIE<"alghsik", 0xECDB, z_uadd, GR64, imm64sx16>, Requires<[FeatureDistinctOps]>; // Addition of unsigned 32-bit immediates. - def ALFI : BinaryRIL<"alfi", 0xC2B, z_uaddo, GR32, uimm32>; - def ALGFI : BinaryRIL<"algfi", 0xC2A, z_uaddo, GR64, imm64zx32>; + def ALFI : BinaryRIL<"alfi", 0xC2B, z_uadd, GR32, uimm32>; + def ALGFI : BinaryRIL<"algfi", 0xC2A, z_uadd, GR64, imm64zx32>; // Addition of signed 32-bit immediates. def ALSIH : BinaryRIL<"alsih", 0xCCA, null_frag, GRH32, simm32>, Requires<[FeatureHighWord]>; // Addition of memory. - defm AL : BinaryRXPair<"al", 0x5E, 0xE35E, z_uaddo, GR32, load, 4>; - def ALGF : BinaryRXY<"algf", 0xE31A, z_uaddo, GR64, azextloadi32, 4>; - def ALG : BinaryRXY<"alg", 0xE30A, z_uaddo, GR64, load, 8>; + defm AL : BinaryRXPair<"al", 0x5E, 0xE35E, z_uadd, GR32, load, 4>; + def ALGF : BinaryRXY<"algf", 0xE31A, z_uadd, GR64, azextloadi32, 4>; + def ALG : BinaryRXY<"alg", 0xE30A, z_uadd, GR64, load, 8>; // Addition to memory. def ALSI : BinarySIY<"alsi", 0xEB6E, null_frag, imm32sx8>; def ALGSI : BinarySIY<"algsi", 0xEB7E, null_frag, imm64sx8>; } -defm : ZXB; +defm : ZXB; // Addition producing and using a carry. let Defs = [CC], Uses = [CC] in { @@ -988,54 +988,6 @@ def ALSIHN : BinaryRIL<"alsihn", 0xCCB, null_frag, GRH32, simm32>, Requires<[FeatureHighWord]>; -// Map plain addition to either arithmetic or logical operation. - -def : Pat<(add GR32:$src1, GR32:$src2), - (AR GR32:$src1, GR32:$src2)>; -def : Pat<(add GR64:$src1, GR64:$src2), - (AGR GR64:$src1, GR64:$src2)>; -defm : SXB; -defm : ZXB; - -def : Pat<(add GRX32:$src1, imm32sx16:$src2), - (AHIMux GRX32:$src1, imm32sx16:$src2)>, Requires<[FeatureHighWord]>; -def : Pat<(add GR32:$src1, imm32sx16:$src2), - (AHI GR32:$src1, imm32sx16:$src2)>; -def : Pat<(add GR64:$src1, imm64sx16:$src2), - (AGHI GR64:$src1, imm64sx16:$src2)>; -def : Pat<(add GRX32:$src1, simm32:$src2), - (AFIMux GRX32:$src1, simm32:$src2)>, Requires<[FeatureHighWord]>; -def : Pat<(add GR32:$src1, simm32:$src2), - (AFI GR32:$src1, simm32:$src2)>; -def : Pat<(add GRH32:$src1, simm32:$src2), - (AIH GRH32:$src1, simm32:$src2)>, Requires<[FeatureHighWord]>; -def : Pat<(add GR64:$src1, imm64sx32:$src2), - (AGFI GR64:$src1, imm64sx32:$src2)>; -def : Pat<(add GR64:$src1, imm64zx32:$src2), - (ALGFI GR64:$src1, imm64zx32:$src2)>; - -def : Pat<(add GR32:$src1, (asextloadi16 bdxaddr12pair:$addr)), - (AH GR32:$src1, bdxaddr12pair:$addr)>; -def : Pat<(add GR32:$src1, (asextloadi16 bdxaddr20pair:$addr)), - (AHY GR32:$src1, bdxaddr20pair:$addr)>; -def : Pat<(add GR32:$src1, (load bdxaddr12pair:$addr)), - (A GR32:$src1, bdxaddr12pair:$addr)>; -def : Pat<(add GR32:$src1, (load bdxaddr20pair:$addr)), - (AY GR32:$src1, bdxaddr20pair:$addr)>; -def : Pat<(add GR64:$src1, (asextloadi16 bdxaddr20only:$addr)), - (AGH GR64:$src1, bdxaddr20only:$addr)>, - Requires<[FeatureMiscellaneousExtensions2]>; -def : Pat<(add GR64:$src1, (asextloadi32 bdxaddr20only:$addr)), - (AGF GR64:$src1, bdxaddr20only:$addr)>; -def : Pat<(add GR64:$src1, (azextloadi32 bdxaddr20only:$addr)), - (ALGF GR64:$src1, bdxaddr20only:$addr)>; -def : Pat<(add GR64:$src1, (load bdxaddr20only:$addr)), - (AG GR64:$src1, bdxaddr20only:$addr)>; - -def : Pat<(store (add (load bdaddr20only:$addr), imm32sx8:$src2), bdaddr20only:$addr), - (ASI bdaddr20only:$addr, imm32sx8:$src2)>; -def : Pat<(store (add (load bdaddr20only:$addr), imm64sx8:$src2), bdaddr20only:$addr), - (AGSI bdaddr20only:$addr, imm64sx8:$src2)>; //===----------------------------------------------------------------------===// // Subtraction @@ -1044,9 +996,9 @@ // Subtraction producing a signed overflow flag. let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0x8 in { // Subtraction of a register. - defm SR : BinaryRRAndK<"sr", 0x1B, 0xB9F9, z_ssubo, GR32, GR32>; + defm SR : BinaryRRAndK<"sr", 0x1B, 0xB9F9, z_ssub, GR32, GR32>; def SGFR : BinaryRRE<"sgfr", 0xB919, null_frag, GR64, GR32>; - defm SGR : BinaryRREAndK<"sgr", 0xB909, 0xB9E9, z_ssubo, GR64, GR64>; + defm SGR : BinaryRREAndK<"sgr", 0xB909, 0xB9E9, z_ssub, GR64, GR64>; // Subtraction from a high register. def SHHHR : BinaryRRFa<"shhhr", 0xB9C9, null_frag, GRH32, GRH32, GRH32>, @@ -1055,39 +1007,39 @@ Requires<[FeatureHighWord]>; // Subtraction of memory. - defm SH : BinaryRXPair<"sh", 0x4B, 0xE37B, z_ssubo, GR32, asextloadi16, 2>; - defm S : BinaryRXPair<"s", 0x5B, 0xE35B, z_ssubo, GR32, load, 4>; - def SGH : BinaryRXY<"sgh", 0xE339, z_ssubo, GR64, asextloadi16, 2>, + defm SH : BinaryRXPair<"sh", 0x4B, 0xE37B, z_ssub, GR32, asextloadi16, 2>; + defm S : BinaryRXPair<"s", 0x5B, 0xE35B, z_ssub, GR32, load, 4>; + def SGH : BinaryRXY<"sgh", 0xE339, z_ssub, GR64, asextloadi16, 2>, Requires<[FeatureMiscellaneousExtensions2]>; - def SGF : BinaryRXY<"sgf", 0xE319, z_ssubo, GR64, asextloadi32, 4>; - def SG : BinaryRXY<"sg", 0xE309, z_ssubo, GR64, load, 8>; + def SGF : BinaryRXY<"sgf", 0xE319, z_ssub, GR64, asextloadi32, 4>; + def SG : BinaryRXY<"sg", 0xE309, z_ssub, GR64, load, 8>; } -defm : SXB; +defm : SXB; // Subtracting an immediate is the same as adding the negated immediate. let AddedComplexity = 1 in { - def : Pat<(z_ssubo GR32:$src1, imm32sx16n:$src2), + def : Pat<(z_ssub GR32:$src1, imm32sx16n:$src2), (AHIMux GR32:$src1, imm32sx16n:$src2)>, Requires<[FeatureHighWord]>; - def : Pat<(z_ssubo GR32:$src1, simm32n:$src2), + def : Pat<(z_ssub GR32:$src1, simm32n:$src2), (AFIMux GR32:$src1, simm32n:$src2)>, Requires<[FeatureHighWord]>; - def : Pat<(z_ssubo GR32:$src1, imm32sx16n:$src2), + def : Pat<(z_ssub GR32:$src1, imm32sx16n:$src2), (AHI GR32:$src1, imm32sx16n:$src2)>; - def : Pat<(z_ssubo GR32:$src1, simm32n:$src2), + def : Pat<(z_ssub GR32:$src1, simm32n:$src2), (AFI GR32:$src1, simm32n:$src2)>; - def : Pat<(z_ssubo GR64:$src1, imm64sx16n:$src2), + def : Pat<(z_ssub GR64:$src1, imm64sx16n:$src2), (AGHI GR64:$src1, imm64sx16n:$src2)>; - def : Pat<(z_ssubo GR64:$src1, imm64sx32n:$src2), + def : Pat<(z_ssub GR64:$src1, imm64sx32n:$src2), (AGFI GR64:$src1, imm64sx32n:$src2)>; } // Subtraction producing a carry. let Defs = [CC] in { // Subtraction of a register. - defm SLR : BinaryRRAndK<"slr", 0x1F, 0xB9FB, z_usubo, GR32, GR32>; + defm SLR : BinaryRRAndK<"slr", 0x1F, 0xB9FB, z_usub, GR32, GR32>; def SLGFR : BinaryRRE<"slgfr", 0xB91B, null_frag, GR64, GR32>; - defm SLGR : BinaryRREAndK<"slgr", 0xB90B, 0xB9EB, z_usubo, GR64, GR64>; + defm SLGR : BinaryRREAndK<"slgr", 0xB90B, 0xB9EB, z_usub, GR64, GR64>; // Subtraction from a high register. def SLHHHR : BinaryRRFa<"slhhhr", 0xB9CB, null_frag, GRH32, GRH32, GRH32>, @@ -1096,26 +1048,32 @@ Requires<[FeatureHighWord]>; // Subtraction of unsigned 32-bit immediates. - def SLFI : BinaryRIL<"slfi", 0xC25, z_usubo, GR32, uimm32>; - def SLGFI : BinaryRIL<"slgfi", 0xC24, z_usubo, GR64, imm64zx32>; + def SLFI : BinaryRIL<"slfi", 0xC25, z_usub, GR32, uimm32>; + def SLGFI : BinaryRIL<"slgfi", 0xC24, z_usub, GR64, imm64zx32>; // Subtraction of memory. - defm SL : BinaryRXPair<"sl", 0x5F, 0xE35F, z_usubo, GR32, load, 4>; - def SLGF : BinaryRXY<"slgf", 0xE31B, z_usubo, GR64, azextloadi32, 4>; - def SLG : BinaryRXY<"slg", 0xE30B, z_usubo, GR64, load, 8>; + defm SL : BinaryRXPair<"sl", 0x5F, 0xE35F, z_usub, GR32, load, 4>; + def SLGF : BinaryRXY<"slgf", 0xE31B, z_usub, GR64, azextloadi32, 4>; + def SLG : BinaryRXY<"slg", 0xE30B, z_usub, GR64, load, 8>; } -defm : ZXB; +defm : ZXB; // Subtracting an immediate is the same as adding the negated immediate. let AddedComplexity = 1 in { - def : Pat<(z_usubo GR32:$src1, imm32sx16n:$src2), + def : Pat<(z_usub GR32:$src1, imm32sx16n:$src2), (ALHSIK GR32:$src1, imm32sx16n:$src2)>, Requires<[FeatureDistinctOps]>; - def : Pat<(z_usubo GR64:$src1, imm64sx16n:$src2), + def : Pat<(z_usub GR64:$src1, imm64sx16n:$src2), (ALGHSIK GR64:$src1, imm64sx16n:$src2)>, Requires<[FeatureDistinctOps]>; } +// And vice versa in one special case (but we prefer addition). +let AddedComplexity = -1 in { + def : Pat<(add GR64:$src1, imm64zx32n:$src2), + (SLGFI GR64:$src1, imm64zx32n:$src2)>; +} + // Subtraction producing and using a carry. let Defs = [CC], Uses = [CC] in { // Subtraction of a register. @@ -1127,35 +1085,6 @@ def SLBG : BinaryRXY<"slbg", 0xE389, z_subcarry, GR64, load, 8>; } -// Map plain subtraction to either arithmetic or logical operation. - -def : Pat<(sub GR32:$src1, GR32:$src2), - (SR GR32:$src1, GR32:$src2)>; -def : Pat<(sub GR64:$src1, GR64:$src2), - (SGR GR64:$src1, GR64:$src2)>; -defm : SXB; -defm : ZXB; - -def : Pat<(add GR64:$src1, imm64zx32n:$src2), - (SLGFI GR64:$src1, imm64zx32n:$src2)>; - -def : Pat<(sub GR32:$src1, (asextloadi16 bdxaddr12pair:$addr)), - (SH GR32:$src1, bdxaddr12pair:$addr)>; -def : Pat<(sub GR32:$src1, (asextloadi16 bdxaddr20pair:$addr)), - (SHY GR32:$src1, bdxaddr20pair:$addr)>; -def : Pat<(sub GR32:$src1, (load bdxaddr12pair:$addr)), - (S GR32:$src1, bdxaddr12pair:$addr)>; -def : Pat<(sub GR32:$src1, (load bdxaddr20pair:$addr)), - (SY GR32:$src1, bdxaddr20pair:$addr)>; -def : Pat<(sub GR64:$src1, (asextloadi16 bdxaddr20only:$addr)), - (SGH GR64:$src1, bdxaddr20only:$addr)>, - Requires<[FeatureMiscellaneousExtensions2]>; -def : Pat<(sub GR64:$src1, (asextloadi32 bdxaddr20only:$addr)), - (SGF GR64:$src1, bdxaddr20only:$addr)>; -def : Pat<(sub GR64:$src1, (azextloadi32 bdxaddr20only:$addr)), - (SLGF GR64:$src1, bdxaddr20only:$addr)>; -def : Pat<(sub GR64:$src1, (load bdxaddr20only:$addr)), - (SG GR64:$src1, bdxaddr20only:$addr)>; //===----------------------------------------------------------------------===// // AND Index: lib/Target/SystemZ/SystemZOperators.td =================================================================== --- lib/Target/SystemZ/SystemZOperators.td +++ lib/Target/SystemZ/SystemZOperators.td @@ -646,6 +646,20 @@ def z_muladd : PatFrag<(ops node:$src1, node:$src2, node:$src3), (add (mul node:$src1, node:$src2), node:$src3)>; +// Alternatives to match operations with or without an overflow CC result. +def z_sadd : PatFrag<(ops node:$src1, node:$src2), + (alternative (z_saddo node:$src1, node:$src2), + (add node:$src1, node:$src2))>; +def z_uadd : PatFrag<(ops node:$src1, node:$src2), + (alternative (z_uaddo node:$src1, node:$src2), + (add node:$src1, node:$src2))>; +def z_ssub : PatFrag<(ops node:$src1, node:$src2), + (alternative (z_ssubo node:$src1, node:$src2), + (sub node:$src1, node:$src2))>; +def z_usub : PatFrag<(ops node:$src1, node:$src2), + (alternative (z_usubo node:$src1, node:$src2), + (sub node:$src1, node:$src2))>; + // Fused multiply-subtract, using the natural operand order. def fms : PatFrag<(ops node:$src1, node:$src2, node:$src3), (fma node:$src1, node:$src2, (fneg node:$src3))>; Index: utils/TableGen/CodeGenDAGPatterns.h =================================================================== --- utils/TableGen/CodeGenDAGPatterns.h +++ utils/TableGen/CodeGenDAGPatterns.h @@ -1188,6 +1188,7 @@ void ParseDefaultOperands(); void ParseInstructions(); void ParsePatterns(); + void EnumerateAlternatives(); void ExpandHwModeBasedTypes(); void InferInstructionFlags(); void GenerateVariants(); Index: utils/TableGen/CodeGenDAGPatterns.cpp =================================================================== --- utils/TableGen/CodeGenDAGPatterns.cpp +++ utils/TableGen/CodeGenDAGPatterns.cpp @@ -1652,7 +1652,42 @@ // TreePatternNode implementation // -static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { +static unsigned GetNumInstructionResults(CodeGenInstruction &InstInfo, + CodeGenDAGPatterns &CDP) { + unsigned NumDefsToAdd = InstInfo.Operands.NumDefs; + + // Subtract any defaulted outputs. + for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) { + Record *OperandNode = InstInfo.Operands[i].Rec; + + if (OperandNode->isSubClassOf("OperandWithDefaultOps") && + !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) + --NumDefsToAdd; + } + + // Add on one implicit def if it has a resolvable type. + if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) != MVT::Other) + ++NumDefsToAdd; + return NumDefsToAdd; +} + +static unsigned GetNumNodeResults(DagInit *Dag, CodeGenDAGPatterns &CDP) { + DefInit *OpDef = dyn_cast(Dag->getOperator()); + assert (OpDef && "Pattern has unexpected operator type!"); + Record *Operator = OpDef->getDef(); + + if (Operator->getName() == "alternative") { + // The number of results of an alternative record is the maximum number + // of results across all alternatives. + unsigned NumResults = 0; + for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) { + DagInit *Alternative = dyn_cast(Dag->getArg(i)); + assert(Alternative && "Invalid DAG alternative"); + NumResults = std::max(NumResults, GetNumNodeResults(Alternative, CDP)); + } + return NumResults; + } + if (Operator->getName() == "set" || Operator->getName() == "implicit") return 0; // All return nothing. @@ -1672,32 +1707,13 @@ // Get the result tree. DagInit *Tree = Operator->getValueAsDag("Fragment"); - Record *Op = nullptr; - if (Tree) - if (DefInit *DI = dyn_cast(Tree->getOperator())) - Op = DI->getDef(); - assert(Op && "Invalid Fragment"); - return GetNumNodeResults(Op, CDP); + assert(Tree && "Invalid Fragment"); + return GetNumNodeResults(Tree, CDP); } if (Operator->isSubClassOf("Instruction")) { CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator); - - unsigned NumDefsToAdd = InstInfo.Operands.NumDefs; - - // Subtract any defaulted outputs. - for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) { - Record *OperandNode = InstInfo.Operands[i].Rec; - - if (OperandNode->isSubClassOf("OperandWithDefaultOps") && - !CDP.getDefaultOperand(OperandNode).DefaultOps.empty()) - --NumDefsToAdd; - } - - // Add on one implicit def if it has a resolvable type. - if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other) - ++NumDefsToAdd; - return NumDefsToAdd; + return GetNumInstructionResults(InstInfo, CDP); } if (Operator->isSubClassOf("SDNodeXForm")) @@ -2236,6 +2252,22 @@ return MadeChange; } + if (getOperator()->getName() == "alternative") { + bool MadeChange = false; + unsigned NC = getNumChildren(); + for (unsigned i = 0; i < NC; ++i) { + TreePatternNode *Child = getChild(i); + MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters); + + // Types of results must match. + for (unsigned j = 0; j < Child->getNumTypes(); j++) { + MadeChange |= Child->UpdateNodeType(j, getExtType(j), TP); + MadeChange |= UpdateNodeType(j, Child->getExtType(j), TP); + } + } + return MadeChange; + } + if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) { bool MadeChange = false; @@ -2461,6 +2493,11 @@ if (!getChild(i)->canPatternMatch(Reason, CDP)) return false; + // For an alternative record to match, we require that *all* alternatives + // can match. This was already checked above. + if (getOperator()->getName() == "alternative") + return true; + // If this is an intrinsic, handle cases that would make it not match. For // example, if an operand is required to be an immediate. if (getOperator()->isSubClassOf("Intrinsic")) { @@ -2626,7 +2663,8 @@ !Operator->isSubClassOf("Intrinsic") && !Operator->isSubClassOf("ComplexPattern") && Operator->getName() != "set" && - Operator->getName() != "implicit") + Operator->getName() != "implicit" && + Operator->getName() != "alternative") error("Unrecognized node '" + Operator->getName() + "'!"); // Check to see if this is something that is illegal in an input pattern. @@ -2635,7 +2673,8 @@ Operator->isSubClassOf("SDNodeXForm")) error("Cannot use '" + Operator->getName() + "' in an input pattern!"); } else { - if (Operator->isSubClassOf("Intrinsic")) + if (Operator->isSubClassOf("Intrinsic") || + Operator->getName() == "alternative") error("Cannot use '" + Operator->getName() + "' in an output pattern!"); if (Operator->isSubClassOf("SDNode") && @@ -2660,10 +2699,6 @@ for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgNameStr(i))); - // Get the actual number of results before Operator is converted to an intrinsic - // node (which is hard-coded to have either zero or one result). - unsigned NumResults = GetNumNodeResults(Operator, CDP); - // If the operator is an intrinsic, then this is just syntactic sugar for // (intrinsic_* , ..children..). Pick the right intrinsic node, and // convert the intrinsic name to a number. @@ -2707,7 +2742,8 @@ } TreePatternNodePtr Result = - std::make_shared(Operator, Children, NumResults); + std::make_shared(Operator, Children, + GetNumNodeResults(Dag, CDP)); Result->setName(OpName); if (Dag->getName()) { @@ -2869,6 +2905,9 @@ ParsePatternFragments(/*OutFrags*/true); ParsePatterns(); + // Break patterns with "alternative" nodes into a series of patterns. + EnumerateAlternatives(); + // Break patterns with parameterized types into a series of patterns, // where each one has a fixed type and is predicated on the conditions // of the associated HW mode. @@ -3571,7 +3610,7 @@ TreePatternNodePtr ResultPattern = std::make_shared( I->getRecord(), ResultNodeOperands, - GetNumNodeResults(I->getRecord(), *this)); + GetNumInstructionResults(CGI, *this)); // Copy fully inferred output node types to instruction result pattern. for (unsigned i = 0; i != NumResults; ++i) { assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled"); @@ -4482,3 +4521,101 @@ LLVM_DEBUG(errs() << "\n"); } } + + +/// EnumerateAlternativesOf - Given a pattern N, generate all permutations we can of +/// the (potentially recursive) pattern by using algebraic laws. +/// +static bool EnumerateAlternativesOf(TreePatternNodePtr N, + std::vector &OutAlternatives) { + + if (N->isLeaf()) + return false; + + if (N->getOperator()->getName() == "alternative") { + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) + if (!EnumerateAlternativesOf(N->getChildShared(i), OutAlternatives)) + OutAlternatives.push_back(N->getChildShared(i)); + + return true; + } + + std::vector > ChildAlternatives; + ChildAlternatives.resize(N->getNumChildren()); + bool FoundAlternative = false; + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) + FoundAlternative |= + EnumerateAlternativesOf(N->getChildShared(i), ChildAlternatives[i]); + + if (!FoundAlternative) + return false; + + // Make sure that each operand has at least one alternative to choose from. + for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) + if (ChildAlternatives[i].empty()) + ChildAlternatives[i].push_back(N->getChildShared(i)); + + // The end result is an all-pairs construction of the resultant pattern. + std::vector Idxs; + Idxs.resize(ChildAlternatives.size()); + bool NotDone; + do { + // Create the variant and add it to the output list. + std::vector NewChildren; + for (unsigned i = 0, e = ChildAlternatives.size(); i != e; ++i) + NewChildren.push_back(ChildAlternatives[i][Idxs[i]]); + TreePatternNodePtr R = std::make_shared( + N->getOperator(), NewChildren, N->getNumTypes()); + + // Copy over properties. + R->setName(N->getName()); + R->setPredicateFns(N->getPredicateFns()); + R->setTransformFn(N->getTransformFn()); + for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) + R->setType(i, N->getExtType(i)); + + // Register alternative. Note this is already guaranteed to fulfil + // canPatternMatch, see the comment there. + OutAlternatives.push_back(R); + + // Increment indices to the next permutation by incrementing the + // indices from last index backward, e.g., generate the sequence + // [0, 0], [0, 1], [1, 0], [1, 1]. + int IdxsIdx; + for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) { + if (++Idxs[IdxsIdx] == ChildAlternatives[IdxsIdx].size()) + Idxs[IdxsIdx] = 0; + else + break; + } + NotDone = (IdxsIdx >= 0); + } while (NotDone); + + return true; +} + + +// EnumerateAlternatives - Expand source patterns containung "alternative" +// nodes into multiple patterns to match. +void CodeGenDAGPatterns::EnumerateAlternatives() { + std::vector Copy = PatternsToMatch; + PatternsToMatch.clear(); + + for (PatternToMatch &P : Copy) { + std::vector Alternatives; + EnumerateAlternativesOf(P.getSrcPatternShared(), Alternatives); + + if (Alternatives.empty()) { + PatternsToMatch.push_back(P); + continue; + } + + for (auto Alternative : Alternatives) { + PatternsToMatch.push_back(PatternToMatch( + P.getSrcRecord(), P.getPredicates(), + Alternative, P.getDstPatternShared(), + P.getDstRegs(), + P.getAddedComplexity(), Record::getNewUID())); + } + } +}