diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index f9f30a8bb70..84e6b1bfefe 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -200,12 +200,15 @@ class RegisterClass regTypes, int alignment, // // (decimate GPR, 2) - Pick every N'th element, starting with the first. // +// (interleave A, B, ...) - Interleave the elements from each argument list. +// // All of these operators work on ordered sets, not lists. That means // duplicates are removed from sub-expressions. // Set operators. The rest is defined in TargetSelectionDAG.td. def sequence; def decimate; +def interleave; // RegisterTuples - Automatically generate super-registers by forming tuples of // sub-registers. This is useful for modeling register sequence constraints diff --git a/test/TableGen/SetTheory.td b/test/TableGen/SetTheory.td index a4acea907d8..4d85aa3e6f2 100644 --- a/test/TableGen/SetTheory.td +++ b/test/TableGen/SetTheory.td @@ -165,3 +165,10 @@ def S9d : Set<(sequence "S%ua", 7, 9)>; // CHECK: S9b = [ e7 e6 e5 e4 e3 ] // CHECK: S9c = [ e0 ] // CHECK: S9d = [ a b c d e0 e3 e6 e9 e4 e5 e7 ] + +// The 'interleave' operator is almost the inverse of 'decimate'. +def interleave; +def T0a : Set<(interleave S9a, S9b)>; +def T0b : Set<(interleave S8e, S8d)>; +// CHECK: T0a = [ e3 e7 e4 e6 e5 ] +// CHECK: T0b = [ e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ] diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp index 838b9246aad..0649fd1cfaf 100644 --- a/utils/TableGen/SetTheory.cpp +++ b/utils/TableGen/SetTheory.cpp @@ -139,6 +139,24 @@ struct DecimateOp : public SetIntBinOp { } }; +// (interleave S1, S2, ...) Interleave elements of the arguments. +struct InterleaveOp : public SetTheory::Operator { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { + // Evaluate the arguments individually. + SmallVector Args(Expr->getNumArgs()); + unsigned MaxSize = 0; + for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) { + ST.evaluate(Expr->getArg(i), Args[i]); + MaxSize = std::max(MaxSize, unsigned(Args[i].size())); + } + // Interleave arguments into Elts. + for (unsigned n = 0; n != MaxSize; ++n) + for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) + if (n < Args[i].size()) + Elts.insert(Args[i][n]); + } +}; + // (sequence "Format", From, To) Generate a sequence of records by name. struct SequenceOp : public SetTheory::Operator { void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) { @@ -211,6 +229,7 @@ SetTheory::SetTheory() { addOperator("rotl", new RotOp(false)); addOperator("rotr", new RotOp(true)); addOperator("decimate", new DecimateOp); + addOperator("interleave", new InterleaveOp); addOperator("sequence", new SequenceOp); }