// compact and readable.
//
-/// PatFrag - Represents a pattern fragment. This can match something on the
-/// DAG, from a single node to multiple nested other fragments.
+/// PatFrags - Represents a set of pattern fragments. Each single fragment
+/// can match something on the DAG, from a single node to multiple nested other
+/// fragments. The whole set of fragments matches if any of the single
+/// fragemnts match. This allows e.g. matching and "add with overflow" and
+/// a regular "add" with the same fragment set.
///
-class PatFrag<dag ops, dag frag, code pred = [{}],
- SDNodeXForm xform = NOOP_SDNodeXForm> : SDPatternOperator {
+class PatFrags<dag ops, list<dag> frags, code pred = [{}],
+ SDNodeXForm xform = NOOP_SDNodeXForm> : SDPatternOperator {
dag Operands = ops;
- dag Fragment = frag;
+ list<dag> Fragments = frags;
code PredicateCode = pred;
code GISelPredicateCode = [{}];
code ImmediateCode = [{}];
ValueType ScalarMemoryVT = ?;
}
+// PatFrag - A version of PatFrags matching only a single fragment.
+class PatFrag<dag ops, dag frag, code pred = [{}],
+ SDNodeXForm xform = NOOP_SDNodeXForm>
+ : PatFrags<ops, [frag], pred, xform>;
+
// OutPatFrag is a pattern fragment that is used as part of an output pattern
// (not an input pattern). These do not have predicates or transforms, but are
// used to avoid repeated subexpressions in output patterns.
: PatFrag<(ops node:$A, node:$B), (P node:$A, (not node:$B))>;
class Su<PatFrag Op>
- : PatFrag<Op.Operands, Op.Fragment, [{ return hasOneUse(N); }],
+ : PatFrag<Op.Operands, !head(Op.Fragments), [{ return hasOneUse(N); }],
Op.OperandTransform>;
// Main selection macros.
// Patfrag to convert the usual comparison patfrags (e.g. setlt) to ones
// that reverse the order of the operands.
class RevCmp<PatFrag F>
- : PatFrag<(ops node:$rhs, node:$lhs), F.Fragment, F.PredicateCode,
+ : PatFrag<(ops node:$rhs, node:$lhs), !head(F.Fragments), F.PredicateCode,
F.OperandTransform>;
def: OpR_RR_pat<C2_cmpeq, seteq, i1, I32>;
// swapped. This relies on the knowledge that the F.Fragment uses names
// "ptr" and "val".
class AtomSt<PatFrag F>
- : PatFrag<(ops node:$val, node:$ptr), F.Fragment, F.PredicateCode,
+ : PatFrag<(ops node:$val, node:$ptr), !head(F.Fragments), F.PredicateCode,
F.OperandTransform> {
let IsAtomic = F.IsAtomic;
let MemoryVT = F.MemoryVT;
}];
let Operands = !if(WithStride, (ops node:$src, node:$ldm), (ops node:$src));
- let Fragment = !foreach(tmp, Operands, !subst(ops, Intr, tmp));
+ let Fragments = [!foreach(tmp, Operands, !subst(ops, Intr, tmp))];
let PredicateCode = !if(!eq(Space, ".shared"), match_shared,
!if(!eq(Space, ".global"), match_global, match_generic));
}
node:$r4, node:$r5, node:$r6, node:$r7));
dag StrideArg = !if(WithStride, (ops node:$ldm), (ops));
let Operands = !con(Args, StrideArg);
- let Fragment = !foreach(tmp, Operands, !subst(ops, Intr, tmp));
+ let Fragments = [!foreach(tmp, Operands, !subst(ops, Intr, tmp))];
let PredicateCode = !if(!eq(Space, ".shared"), match_shared,
!if(!eq(Space, ".global"), match_global, match_generic));
}
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>;
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<z_saddo, GRX32, simm32>,
+ def AFIMux : BinaryRIPseudo<z_sadd, GRX32, simm32>,
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<z_saddo, GR64, AGFR>;
+defm : SXB<z_sadd, GR64, AGFR>;
// 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>;
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<z_uaddo, GR64, ALGFR>;
+defm : ZXB<z_uadd, GR64, ALGFR>;
// Addition producing and using a carry.
let Defs = [CC], Uses = [CC] in {
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<add, GR64, AGFR>;
-defm : ZXB<add, GR64, ALGFR>;
-
-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
// 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>,
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<z_ssubo, GR64, SGFR>;
+defm : SXB<z_ssub, GR64, SGFR>;
// 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>,
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<z_usubo, GR64, SLGFR>;
+defm : ZXB<z_usub, GR64, SLGFR>;
// 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).
+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.
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<sub, GR64, SGFR>;
-defm : ZXB<sub, GR64, SLGFR>;
-
-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
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 : PatFrags<(ops node:$src1, node:$src2),
+ [(z_saddo node:$src1, node:$src2),
+ (add node:$src1, node:$src2)]>;
+def z_uadd : PatFrags<(ops node:$src1, node:$src2),
+ [(z_uaddo node:$src1, node:$src2),
+ (add node:$src1, node:$src2)]>;
+def z_ssub : PatFrags<(ops node:$src1, node:$src2),
+ [(z_ssubo node:$src1, node:$src2),
+ (sub node:$src1, node:$src2)]>;
+def z_usub : PatFrags<(ops node:$src1, node:$src2),
+ [(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))>;
if (Operator->isSubClassOf("SDNode"))
return CDP.getSDNodeInfo(Operator).getNumResults();
- if (Operator->isSubClassOf("PatFrag")) {
+ if (Operator->isSubClassOf("PatFrags")) {
// If we've already parsed this pattern fragment, get it. Otherwise, handle
// the forward reference case where one pattern fragment references another
// before it is processed.
- if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator))
- return PFRec->getOnlyTree()->getNumTypes();
+ if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator)) {
+ // The number of results of a fragment with alternative records is the
+ // maximum number of results across all alternatives.
+ unsigned NumResults = 0;
+ for (auto T : PFRec->getTrees())
+ NumResults = std::max(NumResults, T->getNumTypes());
+ return NumResults;
+ }
- // Get the result tree.
- DagInit *Tree = Operator->getValueAsDag("Fragment");
- Record *Op = nullptr;
- if (Tree)
- if (DefInit *DI = dyn_cast<DefInit>(Tree->getOperator()))
- Op = DI->getDef();
- assert(Op && "Invalid Fragment");
- return GetNumNodeResults(Op, CDP);
+ ListInit *LI = Operator->getValueAsListInit("Fragments");
+ assert(LI && "Invalid Fragment");
+ unsigned NumResults = 0;
+ for (Init *I : LI->getValues()) {
+ Record *Op = nullptr;
+ if (DagInit *Dag = dyn_cast<DagInit>(I))
+ if (DefInit *DI = dyn_cast<DefInit>(Dag->getOperator()))
+ Op = DI->getDef();
+ assert(Op && "Invalid Fragment");
+ NumResults = std::max(NumResults, GetNumNodeResults(Op, CDP));
+ }
+ return NumResults;
}
if (Operator->isSubClassOf("Instruction")) {
/// InlinePatternFragments - If this pattern refers to any pattern
-/// fragments, inline them into place, giving us a pattern without any
-/// PatFrag references.
-TreePatternNodePtr TreePatternNode::InlinePatternFragments(TreePatternNodePtr T,
- TreePattern &TP) {
+/// fragments, return the set of inlined versions (this can be more than
+/// one if a PatFrags record has multiple alternatives).
+void TreePatternNode::InlinePatternFragments(
+ TreePatternNodePtr T, TreePattern &TP,
+ std::vector<TreePatternNodePtr> &OutAlternatives) {
+
if (TP.hasError())
- return nullptr;
+ return;
+
+ if (isLeaf()) {
+ OutAlternatives.push_back(T); // nothing to do.
+ return;
+ }
- if (isLeaf())
- return T; // nothing to do.
Record *Op = getOperator();
- if (!Op->isSubClassOf("PatFrag")) {
- // Just recursively inline children nodes.
+ if (!Op->isSubClassOf("PatFrags")) {
+ if (getNumChildren() == 0) {
+ OutAlternatives.push_back(T);
+ return;
+ }
+
+ // Recursively inline children nodes.
+ std::vector<std::vector<TreePatternNodePtr> > ChildAlternatives;
+ ChildAlternatives.resize(getNumChildren());
for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
TreePatternNodePtr Child = getChildShared(i);
- TreePatternNodePtr NewChild = Child->InlinePatternFragments(Child, TP);
-
- assert((Child->getPredicateFns().empty() ||
- NewChild->getPredicateFns() == Child->getPredicateFns()) &&
- "Non-empty child predicate clobbered!");
+ Child->InlinePatternFragments(Child, TP, ChildAlternatives[i]);
+ // If there are no alternatives for any child, there are no
+ // alternatives for this expression as whole.
+ if (ChildAlternatives[i].empty())
+ return;
- setChild(i, std::move(NewChild));
+ for (auto NewChild : ChildAlternatives[i])
+ assert((Child->getPredicateFns().empty() ||
+ NewChild->getPredicateFns() == Child->getPredicateFns()) &&
+ "Non-empty child predicate clobbered!");
}
- return T;
+
+ // The end result is an all-pairs construction of the resultant pattern.
+ std::vector<unsigned> Idxs;
+ Idxs.resize(ChildAlternatives.size());
+ bool NotDone;
+ do {
+ // Create the variant and add it to the output list.
+ std::vector<TreePatternNodePtr> NewChildren;
+ for (unsigned i = 0, e = ChildAlternatives.size(); i != e; ++i)
+ NewChildren.push_back(ChildAlternatives[i][Idxs[i]]);
+ TreePatternNodePtr R = std::make_shared<TreePatternNode>(
+ getOperator(), NewChildren, getNumTypes());
+
+ // Copy over properties.
+ R->setName(getName());
+ R->setPredicateFns(getPredicateFns());
+ R->setTransformFn(getTransformFn());
+ for (unsigned i = 0, e = getNumTypes(); i != e; ++i)
+ R->setType(i, getExtType(i));
+
+ // Register alternative.
+ 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;
}
// Otherwise, we found a reference to a fragment. First, look up its
if (Frag->getNumArgs() != Children.size()) {
TP.error("'" + Op->getName() + "' fragment requires " +
Twine(Frag->getNumArgs()) + " operands!");
- return {nullptr};
+ return;
}
- TreePatternNodePtr FragTree = Frag->getOnlyTree()->clone();
+ // Compute the map of formal to actual arguments.
+ std::map<std::string, TreePatternNodePtr> ArgMap;
+ for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i) {
+ const TreePatternNodePtr &Child = getChildShared(i);
+ ArgMap[Frag->getArgName(i)] = Child;
+ }
- TreePredicateFn PredFn(Frag);
- if (!PredFn.isAlwaysTrue())
- FragTree->addPredicateFn(PredFn);
+ // Loop over all fragment alternatives.
+ for (auto Alternative : Frag->getTrees()) {
+ TreePatternNodePtr FragTree = Alternative->clone();
- // Resolve formal arguments to their actual value.
- if (Frag->getNumArgs()) {
- // Compute the map of formal to actual arguments.
- std::map<std::string, TreePatternNodePtr> ArgMap;
- for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i) {
- const TreePatternNodePtr &Child = getChildShared(i);
- ArgMap[Frag->getArgName(i)] = Child->InlinePatternFragments(Child, TP);
- }
+ TreePredicateFn PredFn(Frag);
+ if (!PredFn.isAlwaysTrue())
+ FragTree->addPredicateFn(PredFn);
- FragTree->SubstituteFormalArguments(ArgMap);
- }
+ // Resolve formal arguments to their actual value.
+ if (Frag->getNumArgs())
+ FragTree->SubstituteFormalArguments(ArgMap);
- FragTree->setName(getName());
- for (unsigned i = 0, e = Types.size(); i != e; ++i)
- FragTree->UpdateNodeType(i, getExtType(i), TP);
+ // Transfer types. Note that the resolved alternative may have fewer
+ // (but not more) results than the PatFrags node.
+ FragTree->setName(getName());
+ for (unsigned i = 0, e = FragTree->getNumTypes(); i != e; ++i)
+ FragTree->UpdateNodeType(i, getExtType(i), TP);
- // Transfer in the old predicates.
- for (const TreePredicateFn &Pred : getPredicateFns())
- FragTree->addPredicateFn(Pred);
+ // Transfer in the old predicates.
+ for (const TreePredicateFn &Pred : getPredicateFns())
+ FragTree->addPredicateFn(Pred);
- // The fragment we inlined could have recursive inlining that is needed. See
- // if there are any pattern fragments in it and inline them as needed.
- return FragTree->InlinePatternFragments(FragTree, TP);
+ // The fragment we inlined could have recursive inlining that is needed. See
+ // if there are any pattern fragments in it and inline them as needed.
+ FragTree->InlinePatternFragments(FragTree, TP, OutAlternatives);
+ }
}
/// getImplicitType - Check to see if the specified record has an implicit
return TypeSetByHwMode(T.getRegisterClass(R).getValueTypes());
}
- if (R->isSubClassOf("PatFrag")) {
+ if (R->isSubClassOf("PatFrags")) {
assert(ResNo == 0 && "FIXME: PatFrag with multiple results?");
// Pattern fragment types will be resolved when they are inlined.
return TypeSetByHwMode(); // Unknown.
return false;
}
- // special handling for set, which isn't really an SDNode.
- if (getOperator()->getName() == "set") {
- assert(getNumTypes() == 0 && "Set doesn't produce a value");
- assert(getNumChildren() >= 2 && "Missing RHS of a set?");
- unsigned NC = getNumChildren();
-
- TreePatternNode *SetVal = getChild(NC-1);
- bool MadeChange = SetVal->ApplyTypeConstraints(TP, NotRegisters);
-
- for (unsigned i = 0; i < NC-1; ++i) {
- TreePatternNode *Child = getChild(i);
- MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters);
-
- // Types of operands must match.
- MadeChange |= Child->UpdateNodeType(0, SetVal->getExtType(i), TP);
- MadeChange |= SetVal->UpdateNodeType(i, Child->getExtType(0), TP);
- }
- return MadeChange;
- }
-
- if (getOperator()->getName() == "implicit") {
- assert(getNumTypes() == 0 && "Node doesn't produce a value");
-
- bool MadeChange = false;
- for (unsigned i = 0; i < getNumChildren(); ++i)
- MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
- return MadeChange;
- }
-
if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
bool MadeChange = false;
// Direct reference to a leaf DagNode or PatFrag? Turn it into a
// TreePatternNode of its own. For example:
/// (foo GPR, imm) -> (foo GPR, (imm))
- if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag"))
+ if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrags"))
return ParseTreePattern(
DagInit::get(DI, nullptr,
std::vector<std::pair<Init*, StringInit*> >()),
}
// Verify that this is something that makes sense for an operator.
- if (!Operator->isSubClassOf("PatFrag") &&
+ if (!Operator->isSubClassOf("PatFrags") &&
!Operator->isSubClassOf("SDNode") &&
!Operator->isSubClassOf("Instruction") &&
!Operator->isSubClassOf("SDNodeXForm") &&
/// inside a pattern fragment to a pattern fragment.
///
void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
- std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag");
+ std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrags");
// First step, parse all of the fragments.
for (Record *Frag : Fragments) {
if (OutFrags != Frag->isSubClassOf("OutPatFrag"))
continue;
- DagInit *Tree = Frag->getValueAsDag("Fragment");
+ ListInit *LI = Frag->getValueAsListInit("Fragments");
TreePattern *P =
(PatternFragments[Frag] = llvm::make_unique<TreePattern>(
- Frag, Tree, !Frag->isSubClassOf("OutPatFrag"),
+ Frag, LI, !Frag->isSubClassOf("OutPatFrag"),
*this)).get();
// Validate the argument list, converting it to set, to discard duplicates.
// this fragment uses it.
TreePredicateFn PredFn(P);
if (!PredFn.isAlwaysTrue())
- P->getOnlyTree()->addPredicateFn(PredFn);
+ for (auto T : P->getTrees())
+ T->addPredicateFn(PredFn);
// If there is a node transformation corresponding to this, keep track of
// it.
Record *Transform = Frag->getValueAsDef("OperandTransform");
if (!getSDNodeTransform(Transform).second.empty()) // not noop xform?
- P->getOnlyTree()->setTransformFn(Transform);
+ for (auto T : P->getTrees())
+ T->setTransformFn(Transform);
}
// Now that we've parsed all of the tree fragments, do a closure on them so
// Ensure that the inputs agree if we've already seen this input.
if (Rec != SlotRec)
I.error("All $" + Pat->getName() + " inputs must agree with each other");
+ // Ensure that the types can agree as well.
+ Slot->UpdateNodeType(0, Pat->getExtType(0), I);
+ Pat->UpdateNodeType(0, Slot->getExtType(0), I);
if (Slot->getExtTypes() != Pat->getExtTypes())
I.error("All $" + Pat->getName() + " inputs must agree with each other");
return true;
std::map<std::string, TreePatternNodePtr> &InstInputs,
std::map<std::string, TreePatternNodePtr> &InstResults,
std::vector<Record *> &InstImpResults) {
+
+ // The instruction pattern still has unresolved fragments. For *named*
+ // nodes we must resolve those here. This may not result in multiple
+ // alternatives.
+ if (!Pat->getName().empty()) {
+ TreePattern SrcPattern(I.getRecord(), Pat, true, *this);
+ SrcPattern.InlinePatternFragments();
+ SrcPattern.InferAllTypes();
+ Pat = SrcPattern.getOnlyTree();
+ }
+
if (Pat->isLeaf()) {
bool isUse = HandleUse(I, Pat, InstInputs);
if (!isUse && Pat->getTransformFn())
unsigned NumDests = Pat->getNumChildren()-1;
for (unsigned i = 0; i != NumDests; ++i) {
TreePatternNodePtr Dest = Pat->getChildShared(i);
+ // For set destinations we also must resolve fragments here.
+ TreePattern DestPattern(I.getRecord(), Dest, false, *this);
+ DestPattern.InlinePatternFragments();
+ DestPattern.InferAllTypes();
+ Dest = DestPattern.getOnlyTree();
+
if (!Dest->isLeaf())
I.error("set destination should be a register!");
bool mayLoad;
bool isBitcast;
bool isVariadic;
+ bool hasChain;
InstAnalyzer(const CodeGenDAGPatterns &cdp)
: CDP(cdp), hasSideEffects(false), mayStore(false), mayLoad(false),
- isBitcast(false), isVariadic(false) {}
-
- void Analyze(const TreePattern *Pat) {
- // Assume only the first tree is the pattern. The others are clobber nodes.
- AnalyzeNode(Pat->getTree(0).get());
- }
+ isBitcast(false), isVariadic(false), hasChain(false) {}
void Analyze(const PatternToMatch &Pat) {
- AnalyzeNode(Pat.getSrcPattern());
+ const TreePatternNode *N = Pat.getSrcPattern();
+ AnalyzeNode(N);
+ // These properties are detected only on the root node.
+ isBitcast = IsNodeBitcast(N);
}
private:
if (hasSideEffects || mayLoad || mayStore || isVariadic)
return false;
- if (N->getNumChildren() != 2)
+ if (N->isLeaf())
return false;
-
- const TreePatternNode *N0 = N->getChild(0);
- if (!N0->isLeaf() || !isa<DefInit>(N0->getLeafValue()))
+ if (N->getNumChildren() != 1 || !N->getChild(0)->isLeaf())
return false;
- const TreePatternNode *N1 = N->getChild(1);
- if (N1->isLeaf())
- return false;
- if (N1->getNumChildren() != 1 || !N1->getChild(0)->isLeaf())
- return false;
-
- const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N1->getOperator());
+ const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator());
if (OpInfo.getNumResults() != 1 || OpInfo.getNumOperands() != 1)
return false;
return OpInfo.getEnumName() == "ISD::BITCAST";
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
AnalyzeNode(N->getChild(i));
- // Ignore set nodes, which are not SDNodes.
- if (N->getOperator()->getName() == "set") {
- isBitcast = IsNodeBitcast(N);
- return;
- }
-
// Notice properties of the node.
if (N->NodeHasProperty(SDNPMayStore, CDP)) mayStore = true;
if (N->NodeHasProperty(SDNPMayLoad, CDP)) mayLoad = true;
if (N->NodeHasProperty(SDNPSideEffect, CDP)) hasSideEffects = true;
if (N->NodeHasProperty(SDNPVariadic, CDP)) isVariadic = true;
+ if (N->NodeHasProperty(SDNPHasChain, CDP)) hasChain = true;
if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) {
// If this is an intrinsic, analyze it.
InstInfo.mayLoad |= PatInfo.mayLoad;
// These flags are silently added without any verification.
- InstInfo.isBitcast |= PatInfo.isBitcast;
+ // FIXME: To match historical behavior of TableGen, for now add those flags
+ // only when we're inferring from the primary instruction pattern.
+ if (PatDef->isSubClassOf("Instruction")) {
+ InstInfo.isBitcast |= PatInfo.isBitcast;
+ InstInfo.hasChain |= PatInfo.hasChain;
+ InstInfo.hasChain_Inferred = true;
+ }
// Don't infer isVariadic. This flag means something different on SDNodes and
// instructions. For example, a CALL SDNode is variadic because it has the
return false;
}
-const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
+void CodeGenDAGPatterns::parseInstructionPattern(
CodeGenInstruction &CGI, ListInit *Pat, DAGInstMap &DAGInsts) {
assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!");
// Parse the instruction.
- auto I = llvm::make_unique<TreePattern>(CGI.TheDef, Pat, true, *this);
- // Inline pattern fragments into it.
- I->InlinePatternFragments();
-
- // Infer as many types as possible. If we cannot infer all of them, we can
- // never do anything with this instruction pattern: report it to the user.
- if (!I->InferAllTypes())
- I->error("Could not infer all types in pattern!");
+ TreePattern I(CGI.TheDef, Pat, true, *this);
// InstInputs - Keep track of all of the inputs of the instruction, along
// with the record they are declared as.
// Verify that the top-level forms in the instruction are of void type, and
// fill in the InstResults map.
SmallString<32> TypesString;
- for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
+ for (unsigned j = 0, e = I.getNumTrees(); j != e; ++j) {
TypesString.clear();
- TreePatternNodePtr Pat = I->getTree(j);
+ TreePatternNodePtr Pat = I.getTree(j);
if (Pat->getNumTypes() != 0) {
raw_svector_ostream OS(TypesString);
for (unsigned k = 0, ke = Pat->getNumTypes(); k != ke; ++k) {
OS << ", ";
Pat->getExtType(k).writeToStream(OS);
}
- I->error("Top-level forms in instruction pattern should have"
+ I.error("Top-level forms in instruction pattern should have"
" void types, has types " +
OS.str());
}
// Find inputs and outputs, and verify the structure of the uses/defs.
- FindPatternInputsAndOutputs(*I, Pat, InstInputs, InstResults,
+ FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,
InstImpResults);
}
unsigned NumResults = InstResults.size();
// Parse the operands list from the (ops) list, validating it.
- assert(I->getArgList().empty() && "Args list should still be empty here!");
+ assert(I.getArgList().empty() && "Args list should still be empty here!");
// Check that all of the results occur first in the list.
std::vector<Record*> Results;
SmallVector<TreePatternNodePtr, 2> ResNodes;
for (unsigned i = 0; i != NumResults; ++i) {
if (i == CGI.Operands.size())
- I->error("'" + InstResults.begin()->first +
+ I.error("'" + InstResults.begin()->first +
"' set but does not appear in operand list!");
const std::string &OpName = CGI.Operands[i].Name;
// Check that it exists in InstResults.
TreePatternNodePtr RNode = InstResults[OpName];
if (!RNode)
- I->error("Operand $" + OpName + " does not exist in operand list!");
+ I.error("Operand $" + OpName + " does not exist in operand list!");
Record *R = cast<DefInit>(RNode->getLeafValue())->getDef();
ResNodes.push_back(std::move(RNode));
if (!R)
- I->error("Operand $" + OpName + " should be a set destination: all "
+ I.error("Operand $" + OpName + " should be a set destination: all "
"outputs must occur before inputs in operand list!");
if (!checkOperandClass(CGI.Operands[i], R))
- I->error("Operand $" + OpName + " class mismatch!");
+ I.error("Operand $" + OpName + " class mismatch!");
// Remember the return type.
Results.push_back(CGI.Operands[i].Rec);
CGIOperandList::OperandInfo &Op = CGI.Operands[i];
const std::string &OpName = Op.Name;
if (OpName.empty())
- I->error("Operand #" + Twine(i) + " in operands list has no name!");
+ I.error("Operand #" + Twine(i) + " in operands list has no name!");
if (!InstInputsCheck.count(OpName)) {
// If this is an operand with a DefaultOps set filled in, we can ignore
if (!getDefaultOperand(Op.Rec).DefaultOps.empty())
continue;
}
- I->error("Operand $" + OpName +
+ I.error("Operand $" + OpName +
" does not appear in the instruction pattern");
}
TreePatternNodePtr InVal = InstInputsCheck[OpName];
if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) {
Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
if (!checkOperandClass(Op, InRec))
- I->error("Operand $" + OpName + "'s register class disagrees"
+ I.error("Operand $" + OpName + "'s register class disagrees"
" between the operand and pattern");
}
Operands.push_back(Op.Rec);
}
if (!InstInputsCheck.empty())
- I->error("Input operand $" + InstInputsCheck.begin()->first +
- " occurs in pattern but not in operands list!");
+ I.error("Input operand $" + InstInputsCheck.begin()->first +
+ " occurs in pattern but not in operands list!");
TreePatternNodePtr ResultPattern = std::make_shared<TreePatternNode>(
- I->getRecord(), ResultNodeOperands,
- GetNumNodeResults(I->getRecord(), *this));
+ I.getRecord(), ResultNodeOperands,
+ GetNumNodeResults(I.getRecord(), *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");
ResultPattern->setType(i, ResNodes[i]->getExtType(0));
}
+ // FIXME: Assume only the first tree is the pattern. The others are clobber
+ // nodes.
+ TreePatternNodePtr Pattern = I.getTree(0);
+ TreePatternNodePtr SrcPattern;
+ if (Pattern->getOperator()->getName() == "set") {
+ SrcPattern = Pattern->getChild(Pattern->getNumChildren()-1)->clone();
+ } else{
+ // Not a set (store or something?)
+ SrcPattern = Pattern;
+ }
+
// Create and insert the instruction.
// FIXME: InstImpResults should not be part of DAGInstruction.
- Record *R = I->getRecord();
- DAGInstruction &TheInst =
- DAGInsts.emplace(std::piecewise_construct, std::forward_as_tuple(R),
- std::forward_as_tuple(std::move(I), Results, Operands,
- InstImpResults)).first->second;
-
- // Use a temporary tree pattern to infer all types and make sure that the
- // constructed result is correct. This depends on the instruction already
- // being inserted into the DAGInsts map.
- TreePattern Temp(TheInst.getPattern()->getRecord(), ResultPattern, false,
- *this);
- Temp.InferAllTypes(&TheInst.getPattern()->getNamedNodesMap());
-
- TheInst.setResultPattern(Temp.getOnlyTree());
+ Record *R = I.getRecord();
+ DAGInsts.emplace(std::piecewise_construct, std::forward_as_tuple(R),
+ std::forward_as_tuple(Results, Operands, InstImpResults,
+ SrcPattern, ResultPattern));
- return TheInst;
+ LLVM_DEBUG(I.dump());
}
/// ParseInstructions - Parse all of the instructions, inlining and resolving
// Create and insert the instruction.
std::vector<Record*> ImpResults;
Instructions.insert(std::make_pair(Instr,
- DAGInstruction(nullptr, Results, Operands, ImpResults)));
+ DAGInstruction(Results, Operands, ImpResults)));
continue; // no pattern.
}
CodeGenInstruction &CGI = Target.getInstruction(Instr);
- const DAGInstruction &DI = parseInstructionPattern(CGI, LI, Instructions);
-
- (void)DI;
- LLVM_DEBUG(DI.getPattern()->dump());
+ parseInstructionPattern(CGI, LI, Instructions);
}
// If we can, convert the instructions to be patterns that are matched!
for (auto &Entry : Instructions) {
+ Record *Instr = Entry.first;
DAGInstruction &TheInst = Entry.second;
- TreePattern *I = TheInst.getPattern();
- if (!I) continue; // No pattern.
-
- if (PatternRewriter)
- PatternRewriter(I);
- // FIXME: Assume only the first tree is the pattern. The others are clobber
- // nodes.
- TreePatternNodePtr Pattern = I->getTree(0);
- TreePatternNodePtr SrcPattern;
- if (Pattern->getOperator()->getName() == "set") {
- SrcPattern = Pattern->getChild(Pattern->getNumChildren()-1)->clone();
- } else{
- // Not a set (store or something?)
- SrcPattern = Pattern;
- }
+ TreePatternNodePtr SrcPattern = TheInst.getSrcPattern();
+ TreePatternNodePtr ResultPattern = TheInst.getResultPattern();
- Record *Instr = Entry.first;
- ListInit *Preds = Instr->getValueAsListInit("Predicates");
- int Complexity = Instr->getValueAsInt("AddedComplexity");
- AddPatternToMatch(
- I,
- PatternToMatch(Instr, makePredList(Preds), SrcPattern,
- TheInst.getResultPattern(), TheInst.getImpResults(),
- Complexity, Instr->getID()));
+ if (SrcPattern && ResultPattern) {
+ TreePattern Pattern(Instr, SrcPattern, true, *this);
+ TreePattern Result(Instr, ResultPattern, false, *this);
+ ParseOnePattern(Instr, Pattern, Result, TheInst.getImpResults());
+ }
}
}
ArrayRef<const CodeGenInstruction*> Instructions =
Target.getInstructionsByEnumValue();
- // First try to infer flags from the primary instruction pattern, if any.
- SmallVector<CodeGenInstruction*, 8> Revisit;
unsigned Errors = 0;
- for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
- CodeGenInstruction &InstInfo =
- const_cast<CodeGenInstruction &>(*Instructions[i]);
- // Get the primary instruction pattern.
- const TreePattern *Pattern = getInstruction(InstInfo.TheDef).getPattern();
- if (!Pattern) {
- if (InstInfo.hasUndefFlags())
- Revisit.push_back(&InstInfo);
- continue;
- }
- InstAnalyzer PatInfo(*this);
- PatInfo.Analyze(Pattern);
- Errors += InferFromPattern(InstInfo, PatInfo, InstInfo.TheDef);
- }
-
- // Second, look for single-instruction patterns defined outside the
- // instruction.
+ // Try to infer flags from all patterns in PatternToMatch. These include
+ // both the primary instruction patterns (which always come first) and
+ // patterns defined outside the instruction.
for (const PatternToMatch &PTM : ptms()) {
// We can only infer from single-instruction patterns, otherwise we won't
// know which instruction should get the flags.
if (Errors)
PrintFatalError("pattern conflicts");
- // Revisit instructions with undefined flags and no pattern.
+ // If requested by the target, guess any undefined properties.
if (Target.guessInstructionProperties()) {
- for (CodeGenInstruction *InstInfo : Revisit) {
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
+ CodeGenInstruction *InstInfo =
+ const_cast<CodeGenInstruction *>(Instructions[i]);
if (InstInfo->InferredFrom)
continue;
// The mayLoad and mayStore flags default to false.
}
// Complain about any flags that are still undefined.
- for (CodeGenInstruction *InstInfo : Revisit) {
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
+ CodeGenInstruction *InstInfo =
+ const_cast<CodeGenInstruction *>(Instructions[i]);
if (InstInfo->InferredFrom)
continue;
if (InstInfo->hasSideEffects_Unset)
return false;
}
+void CodeGenDAGPatterns::ParseOnePattern(Record *TheDef,
+ TreePattern &Pattern, TreePattern &Result,
+ const std::vector<Record *> &InstImpResults) {
+
+ // Inline pattern fragments and expand multiple alternatives.
+ Pattern.InlinePatternFragments();
+ Result.InlinePatternFragments();
+
+ if (Result.getNumTrees() != 1)
+ Result.error("Cannot use multi-alternative fragments in result pattern!");
+
+ // Infer types.
+ bool IterateInference;
+ bool InferredAllPatternTypes, InferredAllResultTypes;
+ do {
+ // Infer as many types as possible. If we cannot infer all of them, we
+ // can never do anything with this pattern: report it to the user.
+ InferredAllPatternTypes =
+ Pattern.InferAllTypes(&Pattern.getNamedNodesMap());
+
+ // Infer as many types as possible. If we cannot infer all of them, we
+ // can never do anything with this pattern: report it to the user.
+ InferredAllResultTypes =
+ Result.InferAllTypes(&Pattern.getNamedNodesMap());
+
+ IterateInference = false;
+
+ // Apply the type of the result to the source pattern. This helps us
+ // resolve cases where the input type is known to be a pointer type (which
+ // is considered resolved), but the result knows it needs to be 32- or
+ // 64-bits. Infer the other way for good measure.
+ for (auto T : Pattern.getTrees())
+ for (unsigned i = 0, e = std::min(Result.getOnlyTree()->getNumTypes(),
+ T->getNumTypes());
+ i != e; ++i) {
+ IterateInference |= T->UpdateNodeType(
+ i, Result.getOnlyTree()->getExtType(i), Result);
+ IterateInference |= Result.getOnlyTree()->UpdateNodeType(
+ i, T->getExtType(i), Result);
+ }
+
+ // If our iteration has converged and the input pattern's types are fully
+ // resolved but the result pattern is not fully resolved, we may have a
+ // situation where we have two instructions in the result pattern and
+ // the instructions require a common register class, but don't care about
+ // what actual MVT is used. This is actually a bug in our modelling:
+ // output patterns should have register classes, not MVTs.
+ //
+ // In any case, to handle this, we just go through and disambiguate some
+ // arbitrary types to the result pattern's nodes.
+ if (!IterateInference && InferredAllPatternTypes &&
+ !InferredAllResultTypes)
+ IterateInference =
+ ForceArbitraryInstResultType(Result.getTree(0).get(), Result);
+ } while (IterateInference);
+
+ // Verify that we inferred enough types that we can do something with the
+ // pattern and result. If these fire the user has to add type casts.
+ if (!InferredAllPatternTypes)
+ Pattern.error("Could not infer all types in pattern!");
+ if (!InferredAllResultTypes) {
+ Pattern.dump();
+ Result.error("Could not infer all types in pattern result!");
+ }
+
+ // Promote the xform function to be an explicit node if set.
+ const TreePatternNodePtr &DstPattern = Result.getOnlyTree();
+ std::vector<TreePatternNodePtr> ResultNodeOperands;
+ for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) {
+ TreePatternNodePtr OpNode = DstPattern->getChildShared(ii);
+ if (Record *Xform = OpNode->getTransformFn()) {
+ OpNode->setTransformFn(nullptr);
+ std::vector<TreePatternNodePtr> Children;
+ Children.push_back(OpNode);
+ OpNode = std::make_shared<TreePatternNode>(Xform, Children,
+ OpNode->getNumTypes());
+ }
+ ResultNodeOperands.push_back(OpNode);
+ }
+
+ TreePatternNodePtr DstShared =
+ DstPattern->isLeaf()
+ ? DstPattern
+ : std::make_shared<TreePatternNode>(DstPattern->getOperator(),
+ ResultNodeOperands,
+ DstPattern->getNumTypes());
+
+ for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i)
+ DstShared->setType(i, Result.getOnlyTree()->getExtType(i));
+
+ TreePattern Temp(Result.getRecord(), DstShared, false, *this);
+ Temp.InferAllTypes();
+
+ ListInit *Preds = TheDef->getValueAsListInit("Predicates");
+ int Complexity = TheDef->getValueAsInt("AddedComplexity");
+
+ if (PatternRewriter)
+ PatternRewriter(&Pattern);
+
+ // A pattern may end up with an "impossible" type, i.e. a situation
+ // where all types have been eliminated for some node in this pattern.
+ // This could occur for intrinsics that only make sense for a specific
+ // value type, and use a specific register class. If, for some mode,
+ // that register class does not accept that type, the type inference
+ // will lead to a contradiction, which is not an error however, but
+ // a sign that this pattern will simply never match.
+ if (Temp.getOnlyTree()->hasPossibleType())
+ for (auto T : Pattern.getTrees())
+ if (T->hasPossibleType())
+ AddPatternToMatch(&Pattern,
+ PatternToMatch(TheDef, makePredList(Preds),
+ T, Temp.getOnlyTree(),
+ InstImpResults, Complexity,
+ TheDef->getID()));
+}
+
void CodeGenDAGPatterns::ParsePatterns() {
std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern");
TreePattern Pattern(CurPattern, Tree, true, *this);
- // Inline pattern fragments into it.
- Pattern.InlinePatternFragments();
-
ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs");
if (LI->empty()) continue; // no pattern.
// Parse the instruction.
TreePattern Result(CurPattern, LI, false, *this);
- // Inline pattern fragments into it.
- Result.InlinePatternFragments();
-
if (Result.getNumTrees() != 1)
Result.error("Cannot handle instructions producing instructions "
"with temporaries yet!");
- bool IterateInference;
- bool InferredAllPatternTypes, InferredAllResultTypes;
- do {
- // Infer as many types as possible. If we cannot infer all of them, we
- // can never do anything with this pattern: report it to the user.
- InferredAllPatternTypes =
- Pattern.InferAllTypes(&Pattern.getNamedNodesMap());
-
- // Infer as many types as possible. If we cannot infer all of them, we
- // can never do anything with this pattern: report it to the user.
- InferredAllResultTypes =
- Result.InferAllTypes(&Pattern.getNamedNodesMap());
-
- IterateInference = false;
-
- // Apply the type of the result to the source pattern. This helps us
- // resolve cases where the input type is known to be a pointer type (which
- // is considered resolved), but the result knows it needs to be 32- or
- // 64-bits. Infer the other way for good measure.
- for (unsigned i = 0, e = std::min(Result.getTree(0)->getNumTypes(),
- Pattern.getTree(0)->getNumTypes());
- i != e; ++i) {
- IterateInference = Pattern.getTree(0)->UpdateNodeType(
- i, Result.getTree(0)->getExtType(i), Result);
- IterateInference |= Result.getTree(0)->UpdateNodeType(
- i, Pattern.getTree(0)->getExtType(i), Result);
- }
-
- // If our iteration has converged and the input pattern's types are fully
- // resolved but the result pattern is not fully resolved, we may have a
- // situation where we have two instructions in the result pattern and
- // the instructions require a common register class, but don't care about
- // what actual MVT is used. This is actually a bug in our modelling:
- // output patterns should have register classes, not MVTs.
- //
- // In any case, to handle this, we just go through and disambiguate some
- // arbitrary types to the result pattern's nodes.
- if (!IterateInference && InferredAllPatternTypes &&
- !InferredAllResultTypes)
- IterateInference =
- ForceArbitraryInstResultType(Result.getTree(0).get(), Result);
- } while (IterateInference);
-
- // Verify that we inferred enough types that we can do something with the
- // pattern and result. If these fire the user has to add type casts.
- if (!InferredAllPatternTypes)
- Pattern.error("Could not infer all types in pattern!");
- if (!InferredAllResultTypes) {
- Pattern.dump();
- Result.error("Could not infer all types in pattern result!");
- }
-
// Validate that the input pattern is correct.
std::map<std::string, TreePatternNodePtr> InstInputs;
std::map<std::string, TreePatternNodePtr> InstResults;
FindPatternInputsAndOutputs(Pattern, Pattern.getTree(j), InstInputs,
InstResults, InstImpResults);
- // Promote the xform function to be an explicit node if set.
- const TreePatternNodePtr &DstPattern = Result.getOnlyTree();
- std::vector<TreePatternNodePtr> ResultNodeOperands;
- for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) {
- TreePatternNodePtr OpNode = DstPattern->getChildShared(ii);
- if (Record *Xform = OpNode->getTransformFn()) {
- OpNode->setTransformFn(nullptr);
- std::vector<TreePatternNodePtr> Children;
- Children.push_back(OpNode);
- OpNode = std::make_shared<TreePatternNode>(Xform, Children,
- OpNode->getNumTypes());
- }
- ResultNodeOperands.push_back(OpNode);
- }
-
- TreePatternNodePtr DstShared =
- DstPattern->isLeaf()
- ? DstPattern
- : std::make_shared<TreePatternNode>(DstPattern->getOperator(),
- ResultNodeOperands,
- DstPattern->getNumTypes());
-
- for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i)
- DstShared->setType(i, Result.getOnlyTree()->getExtType(i));
-
- TreePattern Temp(Result.getRecord(), DstShared, false, *this);
- Temp.InferAllTypes();
-
- // A pattern may end up with an "impossible" type, i.e. a situation
- // where all types have been eliminated for some node in this pattern.
- // This could occur for intrinsics that only make sense for a specific
- // value type, and use a specific register class. If, for some mode,
- // that register class does not accept that type, the type inference
- // will lead to a contradiction, which is not an error however, but
- // a sign that this pattern will simply never match.
- if (Pattern.getTree(0)->hasPossibleType() &&
- Temp.getOnlyTree()->hasPossibleType()) {
- ListInit *Preds = CurPattern->getValueAsListInit("Predicates");
- int Complexity = CurPattern->getValueAsInt("AddedComplexity");
- if (PatternRewriter)
- PatternRewriter(&Pattern);
- AddPatternToMatch(&Pattern,
- PatternToMatch(CurPattern, makePredList(Preds),
- Pattern.getTree(0), Temp.getOnlyTree(),
- std::move(InstImpResults), Complexity,
- CurPattern->getID()));
- }
+ ParseOnePattern(CurPattern, Pattern, Result, InstImpResults);
}
}
SubstituteFormalArguments(std::map<std::string, TreePatternNodePtr> &ArgMap);
/// InlinePatternFragments - If this pattern refers to any pattern
- /// fragments, inline them into place, giving us a pattern without any
- /// PatFrag references.
- TreePatternNodePtr InlinePatternFragments(TreePatternNodePtr T,
- TreePattern &TP);
+ /// fragments, return the set of inlined versions (this can be more than
+ /// one if a PatFrags record has multiple alternatives).
+ void InlinePatternFragments(TreePatternNodePtr T,
+ TreePattern &TP,
+ std::vector<TreePatternNodePtr> &OutAlternatives);
/// ApplyTypeConstraints - Apply all of the type constraints relevant to
/// this node and its children in the tree. This returns true if it makes a
/// InlinePatternFragments - If this pattern refers to any pattern
/// fragments, inline them into place, giving us a pattern without any
- /// PatFrag references.
+ /// PatFrags references. This may increase the number of trees in the
+ /// pattern if a PatFrags has multiple alternatives.
void InlinePatternFragments() {
- for (unsigned i = 0, e = Trees.size(); i != e; ++i)
- Trees[i] = Trees[i]->InlinePatternFragments(Trees[i], *this);
+ std::vector<TreePatternNodePtr> Copy = Trees;
+ Trees.clear();
+ for (unsigned i = 0, e = Copy.size(); i != e; ++i)
+ Copy[i]->InlinePatternFragments(Copy[i], *this, Trees);
}
/// InferAllTypes - Infer/propagate as many types throughout the expression
};
class DAGInstruction {
- std::unique_ptr<TreePattern> Pattern;
std::vector<Record*> Results;
std::vector<Record*> Operands;
std::vector<Record*> ImpResults;
+ TreePatternNodePtr SrcPattern;
TreePatternNodePtr ResultPattern;
public:
- DAGInstruction(std::unique_ptr<TreePattern> &&TP,
- const std::vector<Record*> &results,
+ DAGInstruction(const std::vector<Record*> &results,
const std::vector<Record*> &operands,
- const std::vector<Record*> &impresults)
- : Pattern(std::move(TP)), Results(results), Operands(operands),
- ImpResults(impresults), ResultPattern(nullptr) {}
+ const std::vector<Record*> &impresults,
+ TreePatternNodePtr srcpattern = nullptr,
+ TreePatternNodePtr resultpattern = nullptr)
+ : Results(results), Operands(operands), ImpResults(impresults),
+ SrcPattern(srcpattern), ResultPattern(resultpattern) {}
- TreePattern *getPattern() const { return Pattern.get(); }
unsigned getNumResults() const { return Results.size(); }
unsigned getNumOperands() const { return Operands.size(); }
unsigned getNumImpResults() const { return ImpResults.size(); }
const std::vector<Record*>& getImpResults() const { return ImpResults; }
- void setResultPattern(TreePatternNodePtr R) { ResultPattern = R; }
-
Record *getResult(unsigned RN) const {
assert(RN < Results.size());
return Results[RN];
return ImpResults[RN];
}
+ TreePatternNodePtr getSrcPattern() const { return SrcPattern; }
TreePatternNodePtr getResultPattern() const { return ResultPattern; }
};
std::vector<Record *> dstregs, int complexity,
unsigned uid, unsigned setmode = 0)
: SrcRecord(srcrecord), SrcPattern(src), DstPattern(dst),
- Predicates(std::move(preds)), Dstregs(std::move(dstregs)),
+ Predicates(preds), Dstregs(dstregs),
AddedComplexity(complexity), ID(uid), ForceMode(setmode) {}
Record *SrcRecord; // Originating Record for the pattern.
/// Parse the Pattern for an instruction, and insert the result in DAGInsts.
typedef std::map<Record*, DAGInstruction, LessRecordByID> DAGInstMap;
- const DAGInstruction &parseInstructionPattern(
+ void parseInstructionPattern(
CodeGenInstruction &CGI, ListInit *Pattern,
DAGInstMap &DAGInsts);
std::vector<Predicate> makePredList(ListInit *L);
+ void ParseOnePattern(Record *TheDef,
+ TreePattern &Pattern, TreePattern &Result,
+ const std::vector<Record *> &InstImpResults);
void AddPatternToMatch(TreePattern *Pattern, PatternToMatch &&PTM);
void FindPatternInputsAndOutputs(
TreePattern &I, TreePatternNodePtr Pat,
ImplicitDefs = R->getValueAsListOfDefs("Defs");
ImplicitUses = R->getValueAsListOfDefs("Uses");
+ // This flag is only inferred from the pattern.
+ hasChain = false;
+ hasChain_Inferred = false;
+
// Parse Constraints.
ParseConstraints(R->getValueAsString("Constraints"), Operands);
bool isConvergent : 1;
bool hasNoSchedulingInfo : 1;
bool FastISelShouldIgnore : 1;
+ bool hasChain : 1;
+ bool hasChain_Inferred : 1;
std::string DeprecatedReason;
bool HasComplexDeprecationPredicate;
if (LHSPatSize < RHSPatSize) return true;
if (LHSPatSize > RHSPatSize) return false;
- // Sort based on the UID of the pattern, giving us a deterministic ordering
- // if all other sorting conditions fail.
- assert(LHS == RHS || LHS->ID != RHS->ID);
+ // Sort based on the UID of the pattern, to reflect source order.
+ // Note that this is not guaranteed to be unique, since a single source
+ // pattern may have been resolved into multiple match patterns due to
+ // alternative fragments. To ensure deterministic output, always use
+ // std::stable_sort with this predicate.
return LHS->ID < RHS->ID;
}
};
// We want to process the matches in order of minimal cost. Sort the patterns
// so the least cost one is at the start.
- llvm::sort(Patterns.begin(), Patterns.end(), PatternSortingPredicate(CGP));
+ std::stable_sort(Patterns.begin(), Patterns.end(),
+ PatternSortingPredicate(CGP));
// Convert each variant of each pattern into a Matcher.
return VarMapEntry-1;
}
- /// GetInstPatternNode - Get the pattern for an instruction.
- const TreePatternNode *GetInstPatternNode(const DAGInstruction &Ins,
- const TreePatternNode *N);
-
void EmitResultOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
void EmitResultOfNamedOperand(const TreePatternNode *N,
N->dump();
}
-/// GetInstPatternNode - Get the pattern for an instruction.
-///
-const TreePatternNode *MatcherGen::
-GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) {
- const TreePattern *InstPat = Inst.getPattern();
-
- // FIXME2?: Assume actual pattern comes before "implicit".
- TreePatternNode *InstPatNode;
- if (InstPat)
- InstPatNode = InstPat->getTree(0).get();
- else if (/*isRoot*/ N == Pattern.getDstPattern())
- InstPatNode = Pattern.getSrcPattern();
- else
- return nullptr;
-
- if (InstPatNode && !InstPatNode->isLeaf() &&
- InstPatNode->getOperator()->getName() == "set")
- InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
-
- return InstPatNode;
-}
-
static bool
mayInstNodeLoadOrStore(const TreePatternNode *N,
const CodeGenDAGPatterns &CGP) {
CodeGenInstruction &II = CGT.getInstruction(Op);
const DAGInstruction &Inst = CGP.getInstruction(Op);
- // If we can, get the pattern for the instruction we're generating. We derive
- // a variety of information from this pattern, such as whether it has a chain.
- //
- // FIXME2: This is extremely dubious for several reasons, not the least of
- // which it gives special status to instructions with patterns that Pat<>
- // nodes can't duplicate.
- const TreePatternNode *InstPatNode = GetInstPatternNode(Inst, N);
-
- // NodeHasChain - Whether the instruction node we're creating takes chains.
- bool NodeHasChain = InstPatNode &&
- InstPatNode->TreeHasProperty(SDNPHasChain, CGP);
-
- // Instructions which load and store from memory should have a chain,
- // regardless of whether they happen to have an internal pattern saying so.
- if (Pattern.getSrcPattern()->TreeHasProperty(SDNPHasChain, CGP) &&
- (II.hasCtrlDep || II.mayLoad || II.mayStore || II.canFoldAsLoad ||
- II.hasSideEffects))
- NodeHasChain = true;
-
bool isRoot = N == Pattern.getDstPattern();
// TreeHasOutGlue - True if this tree has glue.
NumNodesThatLoadOrStore != 1));
}
+ // Determine whether we need to attach a chain to this node.
+ bool NodeHasChain = false;
+ if (Pattern.getSrcPattern()->TreeHasProperty(SDNPHasChain, CGP)) {
+ // For some instructions, we were able to infer from the pattern whether
+ // they should have a chain. Otherwise, attach the chain to the root.
+ //
+ // FIXME2: This is extremely dubious for several reasons, not the least of
+ // which it gives special status to instructions with patterns that Pat<>
+ // nodes can't duplicate.
+ if (II.hasChain_Inferred)
+ NodeHasChain = II.hasChain;
+ else
+ NodeHasChain = isRoot;
+ // Instructions which load and store from memory should have a chain,
+ // regardless of whether they happen to have a pattern saying so.
+ if (II.hasCtrlDep || II.mayLoad || II.mayStore || II.canFoldAsLoad ||
+ II.hasSideEffects)
+ NodeHasChain = true;
+ }
+
assert((!ResultVTs.empty() || TreeHasOutGlue || NodeHasChain) &&
"Node has no result");