New register class and patterns

I’ve added a new register class to my target, but haven’t used any of the new registers in any of the instructions. However when I compile llvm I get the following error:

In SFEQ_ri: Could not infer all types in pattern

Curiously all the instructions where this error occurs are the set flag instructions (flags like zero, less than, greater than etc).

Would anyone be able to figure out why this is happening? I can provide more code if needed.

The error message should show what types have been inferred so far.

You can overcome this problem by specifying the exact type in the pattern, e.g. instead of Class:$Reg, have (i32 Class:$Reg).

This happens when the value can have multiple types what can be represented in the same register class. For example, a 32-bit register could hold i32, v2i16, v4i8, etc. When tablegen cannot figure out which of those it's dealing with, it will complain.

-Krzysztof

I think I understand it. But looks like I have everything labelled
properly. Maybe I missed something. Here are more details:

defm SFEQ : SF<0x0, "l.sfeq", Escala_CC_EQ>;

multiclass SF<bits<5> op2Val, string asmstr, PatLeaf Cond> {
  def _rr : SF_RR<op2Val, asmstr, Cond>;
  def _ri : SF_RI<op2Val, asmstr, Cond>;
}

class SF_RR<bits<5> op2Val, string asmstr, PatLeaf Cond>
  : InstRR<0x9, (outs), (ins GPR:$rA, GPR:$rB),
           !strconcat(asmstr, "\t$rA, $rB"),
           [(Escalasetflag (i32 GPR:$rA), (i32 GPR:$rB), Cond)]> {
  bits<5> op2;
  bits<5> rA;
  bits<5> rB;

  let Inst{25-21} = op2;
  let Inst{20-16} = rA;
  let Inst{15-11} = rB;

  let op2 = op2Val;
}

class SF_RI<bits<5> op2Val, string asmstr, PatLeaf Cond>
  : InstRI<0xf, (outs), (ins GPR:$rA, s16imm:$imm),
           !strconcat(asmstr, "i\t$rA, $imm"),
           [(Escalasetflag (i32 GPR:$rA), immSExt16:$imm, Cond)]> {
  bits<5> op2;
  bits<5> rA;
  bits<16> imm;

  let Inst{25-21} = op2;
  let Inst{20-16} = rA;
  let Inst{15-0} = imm;

  let format = AFrm;
  let op2 = op2Val;
}

I would appreciate any feedback.

It sounds to me like you are missing the type for the output. If you’re setting an implicit register,
you need something like [(set FLAGS, (Escalasetflag i32:$rA, i32:$rB, Cond))]. You also need a corresponding let Defs = [FLAGS], although that’s unrelated to the pattern problem. Assuming EFLAGS has a single type added to it, you don’t need to explicitly add one.

Also note you should not need to specify the register class in the pattern. i32:$sA should work etc.

-Matt

Here is what I have defined for Escalasetflag

def Escalasetflag : SDNode<"EscalaISD::SET_FLAG", SDT_EscalaSetFlag,
                             [SDNPOutGlue]>;

How come it was working before and is is not working now? Clearly I'm
missing something, but I can't figure out what.

Any help is appreciated.

Let me clarify.

I'm not sure I understand what you are saying. Let me post more information.

Here is what I have defined for Escalasetflag

def Escalasetflag : SDNode<"EscalaISD::SET_FLAG", SDT_EscalaSetFlag,
                             [SDNPOutGlue]>;

How come it was working before and is is not working now? Clearly I'm
missing something, but I can't figure out what.

Any help is appreciated.

What is SDT_EscalaSetFlag?

Let me clarify.

I'm not sure I understand what you are saying. Let me post more
information.

Here is what I have defined for Escalasetflag

def Escalasetflag : SDNode<"EscalaISD::SET_FLAG", SDT_EscalaSetFlag,
                             [SDNPOutGlue]>;

How come it was working before and is is not working now? Clearly I'm
missing something, but I can't figure out what.

Any help is appreciated.

--
Rail Shafigulin
Software Engineer
Esencia Technologies

What is SDT_EscalaSetFlag?

def SDT_EscalaSetFlag : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>]>;

Any recommendations? Would anyone be able to point out what am I missing?

I think for setting an implicit register, you still need to have 1 result here.

If you look at SDTX86CmpPTest, I think this is similar to what you are trying to do.

-Matt

As usual, any insight into the issue and any help is greatly appreciated.

The results are numbered starting from 0. In this case with 1 result, 0 is the output operand, and 1 and 2 are the inputs.

Did you add a register class for a special condition register? Did you set it as isAllocatable = 0?

It does have an output register, it's just an implicit flag register. It still has a DAG output. I'm not sure if the allocatable bit matters at this point for selection purposes, but it does later. Not adding a type to the register class can also be problematic (e.g. a flag register should have i1 added to regTypes for its class).

-Matt

It does have an output register, it's just an implicit flag register. It
still has a DAG output. I'm not sure if the allocatable bit matters at this
point for selection purposes, but it does later. Not adding a type to the
register class can also be problematic (e.g. a flag register should have i1
added to regTypes for its class).

-Matt

Does LLVM make an assumption that there is an implicit register output if
there are no outputs given to the pattern? I'm also curious about how did
LLVM know that an output of this instruction was setting a flag in a
special purpose register rather than a GPR? When I look at the DAG pattern
for the instruction, (Escalasetflag (i32 GPR:$rA), immSExt16:$imm, Cond), I
can't find anything saying that it sets a flag in the special purpose
register.

I'm reposting code for convenience.

def SDT_EscalaSetFlag : SDTypeProfile<0, 3, [SDTCisSameAs<0, 1>]>;

def Escalatflag : SDNode<"EscalaISD::SET_FLAG", SDT_EscalaSetFlag,
                             [SDNPOutGlue]>;

def Escala_CC_EQ : PatLeaf<(imm),
                  [{return (N->getZExtValue() == ISD::SETEQ);}]>;

class SF_RI<bits<5> op2Val, string asmstr, PatLeaf Cond>
  : InstRI<0xf, (outs), (ins GPR:$rA, s16imm:$imm),
           !strconcat(asmstr, "i\t$rA, $imm"),
           [(Escalasetflag (i32 GPR:$rA), immSExt16:$imm, Cond)]> {
  bits<5> op2;
  bits<5> rA;
  bits<16> imm;

  let Inst{25-21} = op2;
  let Inst{20-16} = rA;
  let Inst{15-0} = imm;

  let format = AFrm;
  let op2 = op2Val;
}

multiclass SF<bits<5> op2Val, string asmstr, PatLeaf Cond> {
  def _rr : SF_RR<op2Val, asmstr, Cond>;
  def _ri : SF_RI<op2Val, asmstr, Cond>;
}

defm SFEQ : SF<0x0, "l.sfeq", Escala_CC_EQ>;

No, this would have to be a void side effecting instruction which is a bit different. The flag register is an implicit register added to the selected MachineInstr's operands.

-Matt

No, this would have to be a void side effecting instruction which is a bit
different.

What do you mean by "void side effecting instruction"? I'm not sure I
fully understand what you mean.

The flag register is an implicit register added to the selected

MachineInstr's operands.

Is this something that is always done by LLVM? Is it me who is telling to
LLVM to do it? I'd appreciate if you could point out where in the code this
is happening.

I've also followed your advice and added i1 as a type for my SPR

def SPR : RegisterClass<"Esencia", [i1,i32], 32, (add SR)> {
  let CopyCost = -1; // Don't allow copying of special purpose registers.
  let isAllocatable = 0;
}

Then I changed an instruction class to return an explicit value

class SF_RR<bits<5> op2Val, string asmstr, PatLeaf Cond> :
    InstRR<0x9, (outs), (ins GPR:$rA, GPR:$rB),
                !strconcat(asmstr, "\t$rA, $rB"),
                [(set SPR:$rC, (Esenciasetflag (i32 GPR:$rA), (i32
GPR:$rB), Cond))]> {
  bits<5> op2;
  bits<5> rA;
  bits<5> rB;

  let Inst{25-21} = op2;
  let Inst{20-16} = rA;
  let Inst{15-11} = rB;

  let op2 = op2Val;
}

Naturally LLVM didn't like it. I'm getting stack dumps when I compile it.
I'm assuming this is happening because LLVM is not expecting to see an
explicit output. As far as I understand my options are:

1. Have an instruction return an explicit value, but then I will have to do
a lot of work to change a large chunk of the backend.
2. Continue working with an implicit value being set by an instruction.

I'd like to introduce as little changes as I can. So option 2 seems to be a
reasonable one, however I can't figure out where and what I need to change.
As most people on this list, I'm also learning "on the fly"

I'd really appreciate any help on this.

You should add a let Defs = [FLAGREGISTERNAME] on the defining instruction

-Matt

Well, as it turns out it is already done :frowning:

let Defs = [SR], hasSideEffects = 1 in {
  let Itinerary = l_sfeq in
    defm SFEQ : SF<0x0, "l.sfeq", Escala_CC_EQ>;
.....
}

And I'm still getting an error:

Sorry, previous email went out by mistake.

Well, as it turns out it is already done :frowning:

let Defs = [SR], hasSideEffects = 1 in {
  let Itinerary = l_sfeq in
    defm SFEQ : SF<0x0, "l.sfeq", Escala_CC_EQ>;
.....
}

And I'm still getting an error:
error: In SFEQ_ri: Could not infer all types in pattern!
    defm SFEQ : SF<0x0, "l.sfeq", Escala_CC_EQ>;

What else I should be looking at?