================ @@ -233,6 +327,126 @@ RegBankLegalizeRules::getRulesForOpc(MachineInstr &MI) const { return GRules.at(GRulesAlias.at(Opc)); } +// Syntactic sugar wrapper for predicate lambda that enables '&&', '||' and '!'. +class Predicate { +public: + struct Elt { + // Save formula composed of Pred, '&&', '||' and '!' as a jump table. + // Sink ! to Pred. For example !((A && !B) || C) -> (!A || B) && !C + // Sequences of && and || will be represented by jumps, for example: + // (A && B && ... X) or (A && B && ... X) || Y + // A == true jump to B + // A == false jump to end or Y, result is A(false) or Y + // (A || B || ... X) or (A || B || ... X) && Y + // A == true jump to end or Y, result is B(true) or Y + // A == false jump to B + // Notice that when negating expression, we simply flip Neg on each Pred + // and swap TJumpOffset and FJumpOffset (&& becomes ||, || becomes &&). + std::function<bool(const MachineInstr &)> Pred; + bool Neg; // Neg of Pred is calculated before jump + unsigned TJumpOffset; + unsigned FJumpOffset; + }; + + SmallVector<Elt, 8> Expression; + + Predicate(std::function<bool(const MachineInstr &)> Pred) { + Expression.push_back({Pred, false, 1, 1}); + }; + + Predicate(SmallVectorImpl<Elt> &Expr) { Expression.swap(Expr); }; + + bool operator()(const MachineInstr &MI) const { + unsigned Idx = 0; + unsigned ResultIdx = Expression.size(); + bool Result; + do { + Result = Expression[Idx].Pred(MI); + Result = Expression[Idx].Neg ? !Result : Result; + if (Result) { + Idx += Expression[Idx].TJumpOffset; + } else { + Idx += Expression[Idx].FJumpOffset; + } + } while ((Idx != ResultIdx)); + + return Result; + }; + + Predicate operator!() { + SmallVector<Elt, 8> NegExpression; + for (Elt &ExprElt : Expression) { + NegExpression.push_back({ExprElt.Pred, !ExprElt.Neg, ExprElt.FJumpOffset, + ExprElt.TJumpOffset}); + } + return Predicate(NegExpression); + }; + + Predicate operator&&(Predicate &RHS) { ---------------- nhaehnle wrote:
Similar to the constructor above, the baseline of this should be a const method that accepts a const reference as an argument. Do you have a good argument for the rvalue-argument overload below? If not, please just remove it. The same applies to `operator||`. https://github.com/llvm/llvm-project/pull/112882 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits