Description
Here is the code that triggers this issue (please paste boilerplate code from test/TableGen/GlobalISelEmitterCustomPredicate.td
at the beginning of this file). Also, this bug follows up the patch presented in #68125.
def DOP : RegisterOperand<DRegs>;
def MUL_OR : I<(outs DRegs:$dst), (ins DOP:$src0, DOP:$src1, DOP:$src2), []>;
def or_complex_pattern : ComplexPattern<i32, 2, "selectOrComplex">;
def mul_pat : PatFrag<
(ops node:$x, node:$y),
(mul node:$x, node:$y), [{ ... }]> {
let GISelPredicateCode = [{ ... }];
let PredicateCodeUsesOperands = 1;
}
def : Pat<
(i32 (mul_pat (or_complex_pattern DOP:$src0, DOP:$src1), DOP:$src2)),
(MUL_OR DOP:$src0, DOP:$src1, DOP:$src2)
>;
When running with -gen-global-isel
, llvm-tblgen cashes with the following message:
llvm-project/llvm/utils/TableGen/GlobalISelEmitter.cpp:775: Expected<llvm::gi::InstructionMatcher &> (anonymous namespace)::GlobalISelEmitter::createAndImportSelDAGMatcher(llvm::gi::RuleMatcher &, llvm::gi::InstructionMatcher &, const llvm::TreePatternNode *, unsigned int &): Assertion `WaitingForNamedOperands == 0 && "previous predicate didn't find all operands or " "nested predicate that uses operands"' failed.
Here is the root cause: WaitingForNamedOperands
is a counter that keeps tracks of operand mapping while using GISelPredicateCode
+ PredicateCodeUsesOperands = 1
. It's subtracted by one for each PatFrag operand and it should be zero, namely the assertion message, before we start processing another PatFrag.
For instance, when processing (mul_pat (or_complex_pattern DOP:$src0, DOP:$src1), DOP:$src2)
, WaitingForNamedOperands
is initialized with 2, the number of PatFrag operands. It is subtracted by 1 after (or_complex_pattern DOP:$src0, DOP:$src1)
is handled, but since or_complex_pattern
has no GISel counterpart, GlobalISelEmitter bails out (too) early and skips DOP:$src2
entirely, leaving WaitingForNamedOperands
a non-zero value, hence the assertion failure.