How do I read "Type set is empty for each HW mode"?

Hi *

For my educational project (MC6809 backend), I’m trying to write a Pat<> to match a compare/branch combination.

I’m aiming for 100% pattern importing by GlobalISel, as I’ve discovered it does a much better job than my manual lowering efforts.

The TableGen GlobalISel pattern importer is objecting to this (simplified a bit):

def : Pat<(brcond (i8 (setcc ACC8:$src, (i8 imm:$val), SETEQ)), bb:$tgt), 
(ConditionalBranchRelative (i8 12), bb:$tgt, (Compare_i8_Imm ACC8:$src, i8imm:$val))>;

… where ConditionalBranchRelative and Compare_i8_Imm are pseudo-instructions that I lower further once the register allocator is done The (i8 12) is how I’m passing the SETEQ condition to the condtional branch instruction. The i1 bit returned by the comparison and consumed by the branch is thrown away shortly after this, and the condition register bits carry the results of the comparison.

The objection is:

Type set is empty for each HW mode:
possible type contradiction in the pattern below (use -print-records with llvm-tblgen to see all expanded records).
CompBraPat_i8_Imm: 	(ConditionalBranchRelative 12:{ *:[] }, (bb:{}):$tgt, (Compare_i8_Imm:{} ACC8:{}:$src, i8imm:{}:$val))
Generated from record:
CompBraPat_i8_Imm {	// Pattern Pat
  dag PatternToMatch = (brcond (i8 (setcc ACC8:$src, (i8 imm:$val), SETEQ)), bb:$tgt);
  list<dag> ResultInstrs = [(ConditionalBranchRelative (i8 12), bb:$tgt, (Compare_i8_Imm ACC8:$src, i8imm:$val))];
  list<Predicate> Predicates = [];
  int AddedComplexity = 0;
}

I have little idea how to even read this. What is it objecting to? The usual web searches have given me hints about operand size incompatibilities, but I can’t see what it doesn’t like.

I’ve been able to make similar problems go away before by fiddling, but I don’t really know what I did to fix it. In this case, the usual frobs are not helping.

Could some kind soul please explain how I can find where the error lies? I’ve tried peeking inside TableGen with a debugger, but not knowing what to look for is making my confusion worse, and there is a lot of detail in the above report.

Thanks!

M

Long story short, it means that the type inference has eliminated every potential type for 12: 12:{ *:[] } The * means any HW mode not explicitly listed in the {}. For targets that don’t use HW modes, this part can be ignored. The [] lists possible types for the value before :, in this case for 12. Here the list of types is empty, hence the error.

Tracking down such things can be tricky. I’m guessing that the type assumed for immediates at some point differs from i8, and the type intersection ends up being an empty set.

Thanks for the response!

That point had sorta occurred to me, and I thought I’d fixed it by writing the 12 as (i8 12) (I just tried writing it just as 12 to no avail).

Is there a better way to hand a constant to an instruction such that I can later inspect it (as an operand?) if I have to? I can be crude and create a bunch of different BranchEq, BranchNEq, etc instructions, but that is the kind of verbosity that I’d really like to avoid.

M

How is ConditionalBranchRelative defined? What is the type of the operand that would become 12 in this pattern?

This is an area of frequent frobbing :slightly_frowning_face:

Slightly stripped down (the parent class only contains thins like isBranch and so on):

class MC6809ConditionalBranch : MC6809Branch {
  dag InOperandList = (ins condcode:$cc, label:$tgt, BIT1:$bits);
}

def ConditionalBranchRelative : MC6809ConditionalBranch;

The $bits field is intended to be a proxy for the NZVC bits in CC, and condcode is the EQ, NE, LT etc property, defined as:

def condcode : Operand<OtherVT> {
  let EncoderMethod = "encodeCondCodeOpValue";
  let ParserMatchClass = CondCodeAsmOperand<"CondCode">;
  let PrintMethod = "printCondCode";
}

M

I think your question was enough of a hint to check my condcode definition. I changed it to

def condcode : Operand<i4> {
  let EncoderMethod = "encodeCondCodeOpValue";
  let ParserMatchClass = CondCodeAsmOperand<"CondCode">;
  let PrintMethod = "printCondCode";
}

… and I was enlightened!

Thanks also for pointing out the significance of the [] vs [i8] in the error I got. That also helped :slight_smile:

M

1 Like