[llvm-dev] TableGen Instruction class Uses and Defs

226 views
Skip to first unread message

Miguel Inigo J. Manalac via llvm-dev

unread,
Mar 1, 2020, 8:42:26 PM3/1/20
to llvm-dev

Hello LLVM-Dev,

 

I understand that Uses and Defs are for implicit registers. Uses is defined as for using non-operand registers and Defs is defined as for modifying non-operand registers.

 

For example, for compare and compare with carry instructions, is my understanding correct that the instructions should be defined as described below?

Considering that the carry flag is part of the status register:

Compare – The status register is only listed in the Defs register list since it modifies the status register.

Compare with carry – The status register is listed in both Defs and Uses register lists since it refers the status register (Carry flag information) and modifies it.

 

With this understanding, am I correct to assume that all “with carry” instructions lists the status register in the Uses? The status register being listed in the Defs depends on whether the instruction modifies the status register or not.

 

Thank you in advance for your responses, they are highly appreciated.

 

Sincerely,

Miguel Inigo J. Manalac (1852)

 

JAPANESE: このメールは、宛先に書かれている方のみに送信することを意図しております。誤ってそれ以外の方に送信された場合は、申し訳ございませんが、送信者までお知らせいただき、受信されたメールを削除していただきますようお願いいたします。また、コンピュータ・ウィルスの混入等によってメールの欠落・不整合・遅滞等が発生し、何らのご不便をおかけすることが生じても弊社はその責任を負いません。 ENGLISH: This e-mail is intended for the person(s) to which it is addressed. If you have received it by mistake, please notify the sender and delete the received email. In addition, our company shall not assume any responsibility even if it causes any inconvenience, such as loss of mail, inconsistencies, delays, etc., due to the inclusion of computer viruses.

Nicolai Hähnle via llvm-dev

unread,
Mar 2, 2020, 9:44:24 AM3/2/20
to Miguel Inigo J. Manalac, llvm-dev
Hi Miguel,

On Mon, Mar 2, 2020 at 2:42 AM Miguel Inigo J. Manalac via llvm-dev
<llvm...@lists.llvm.org> wrote:
> For example, for compare and compare with carry instructions, is my understanding correct that the instructions should be defined as described below?
>
> Considering that the carry flag is part of the status register:
>
> Compare – The status register is only listed in the Defs register list since it modifies the status register.
> Compare with carry – The status register is listed in both Defs and Uses register lists since it refers the status register (Carry flag information) and modifies it.
>
> With this understanding, am I correct to assume that all “with carry” instructions lists the status register in the Uses? The status register being listed in the Defs depends on whether the instruction modifies the status register or not.

Yes, this is the typical way to define such instructions.

Cheers,
Nicolai

>
>
>
> Thank you in advance for your responses, they are highly appreciated.
>
>
>
> Sincerely,
>
> Miguel Inigo J. Manalac (1852)
>
>
>
> JAPANESE: このメールは、宛先に書かれている方のみに送信することを意図しております。誤ってそれ以外の方に送信された場合は、申し訳ございませんが、送信者までお知らせいただき、受信されたメールを削除していただきますようお願いいたします。また、コンピュータ・ウィルスの混入等によってメールの欠落・不整合・遅滞等が発生し、何らのご不便をおかけすることが生じても弊社はその責任を負いません。 ENGLISH: This e-mail is intended for the person(s) to which it is addressed. If you have received it by mistake, please notify the sender and delete the received email. In addition, our company shall not assume any responsibility even if it causes any inconvenience, such as loss of mail, inconsistencies, delays, etc., due to the inclusion of computer viruses.
> _______________________________________________
> LLVM Developers mailing list
> llvm...@lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev



--
Lerne, wie die Welt wirklich ist,
aber vergiss niemals, wie sie sein sollte.
_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

Miguel Inigo J. Manalac via llvm-dev

unread,
Mar 2, 2020, 5:54:30 PM3/2/20
to Nicolai Hähnle, llvm-dev
Hello Nicolai,

Thank you for your help! I understand its use now.

Best,
Miguel

Marco Speziali via llvm-dev

unread,
Apr 10, 2021, 12:19:12 PM4/10/21
to llvm...@lists.llvm.org
Dear all,

I need to implement the following behavior for all instructions that
require two source operands:

%1 = add i16 %a, %b

Should match the ADD instruction which has 1 outs and 1 ins. The second
operand %b should be moved into the implicit register R14 (fixed).
For now I implemented the PseudoADD instruction which gets expanded into
a move plus the mentioned ADD instruction.
This obviously creates a low of unnecessary moves and prevents any
optimizations of the register R14 (e.g. R14 could be used as destination
register in previous operations without the need for a move).

I'd like to transform the dag:

(set GPR:$rd, (add GPR:$rs1, GPR:$rs2))

to something like:

(set R14, GPR:$rs2), (set GPR:$rd, (add GPR:$rs1))

Is it possible to specify this transformation using TableGen? If now how
could I achieve this?


Thanks.

Best Regards,
Marco Speziali

Craig Topper via llvm-dev

unread,
Apr 10, 2021, 1:10:04 PM4/10/21
to Marco Speziali, llvm...@lists.llvm.org
In tablegen you can write

(set GPR:$rd, (add GPR:$rs1, R14))
--
~Craig

Craig Topper via llvm-dev

unread,
Apr 10, 2021, 6:06:41 PM4/10/21
to Marco Speziali, llvm...@lists.llvm.org
Here's an example from X86 that reads XMM0. The "let Uses = [XMM0]" adds an implicit physical register input for XMM0. The outs and ins list the other virtual register inputs. The pattern uses XMM0 as an operand like the (set GPR:$rd, (add GPR:$rs1, R14)).

let Uses = [XMM0], Constraints = "$src1 = $dst" in {
  multiclass SS41I_ternary<bits<8> opc, string OpcodeStr, ValueType VT,
                           PatFrag mem_frag, X86MemOperand x86memop,
                           SDNode OpNode, X86FoldableSchedWrite sched> {
    def rr0 : SS48I<opc, MRMSrcReg, (outs VR128:$dst),
                    (ins VR128:$src1, VR128:$src2),
                    !strconcat(OpcodeStr,
                     "\t{%xmm0, $src2, $dst|$dst, $src2, xmm0}"),
                    [(set VR128:$dst,
                      (VT (OpNode XMM0, VR128:$src2, VR128:$src1)))]>,
                    Sched<[sched]>;

    def rm0 : SS48I<opc, MRMSrcMem, (outs VR128:$dst),
                    (ins VR128:$src1, x86memop:$src2),
                    !strconcat(OpcodeStr,
                     "\t{%xmm0, $src2, $dst|$dst, $src2, xmm0}"),
                    [(set VR128:$dst,
                      (OpNode XMM0, (mem_frag addr:$src2), VR128:$src1))]>,
                    Sched<[sched.Folded, sched.ReadAfterFold]>;
  }
}

Here's another more complex example. This one has an input in AL and an output in AL, EFLAGS, and AH. We listed AX in the implicit defs for both AL and AH for some reason.

let Defs = [AL,EFLAGS,AX], Uses = [AL] in
def MUL8r  : I<0xF6, MRM4r, (outs),  (ins GR8:$src), "mul{b}\t$src",
               // FIXME: Used for 8-bit mul, ignore result upper 8 bits.
               // This probably ought to be moved to a def : Pat<> if the
               // syntax can be accepted.
               [(set AL, (mul AL, GR8:$src)),
                (implicit EFLAGS)]>, Sched<[WriteIMul8]>;

~Craig


On Sat, Apr 10, 2021 at 2:46 PM Marco Speziali <marco.s...@mail.polimi.it> wrote:
Dear Craig,
Thanks for the reply. I tried to use the pattern you provided to set list<pattern> inside the ADD instruction. Unfortunately the pattern:

(set GPR:$rd, (add GPR:$rs1, R14))

Does not generate a move of $rs2 to R14. It, for some reason, produces an add with 3 register operands. Which we do not support. The only way to use 2 source registers is to move the second one to R14. For example:

add rd, rs1, rs2

Should become:

mv R14, rs2
add rd, rs1

Is there a way to automate this process using TableGen?

Thanks,
Marco Speziali

Marco Speziali via llvm-dev

unread,
Apr 11, 2021, 12:44:33 PM4/11/21
to Craig Topper, llvm...@lists.llvm.org
Dear Craig,
Thanks for the reply. I tried to use the pattern you provided to set list<pattern> inside the ADD instruction. Unfortunately the pattern:

(set GPR:$rd, (add GPR:$rs1, R14))

Does not generate a move of $rs2 to R14. It, for some reason, produces an add with 3 register operands. Which we do not support. The only way to use 2 source registers is to move the second one to R14. For example:

add rd, rs1, rs2

Should become:

mv R14, rs2
add rd, rs1

Is there a way to automate this process using TableGen?

Thanks,
Marco Speziali
On 10 Apr 2021, at 19:09, Craig Topper <craig....@gmail.com> wrote:

Marco Speziali via llvm-dev

unread,
Apr 11, 2021, 12:45:13 PM4/11/21
to Craig Topper, llvm...@lists.llvm.org
Dear Craig,
it now works as intended.

Thank you so much,
Marco Speziali

Marco Speziali via llvm-dev

unread,
Apr 11, 2021, 12:45:28 PM4/11/21
to Craig Topper, llvm...@lists.llvm.org
Dear Craig,
I have an other small question if possibile. In my case also branches and stores follows the same rule (second source register must be moved into W).

I have this pattern:

def : Pat<
  (brcond GPR:$cond, bb:$imm),
  (PseudoBNE GPR:$cond, 0, imm16bb:$imm)
>;

Used for brcond without sect (i.e. condition calculated elsewhere). I’d like to remove the PseudoBNE and use BNE (with a single source register). But I cannot figure out how to tell TableGen that 0 must be moved into R14.
Other patterns I need to convert are:

def : Pat<
  (truncstorei8 GPR:$src, (i16 (isabella_wrapper tglobaladdr:$dst))),
  (PseudoSB GPR:$src, R0, tglobaladdr:$dst)
>;
def : Pat<
  (store GPR:$src, (i16 (isabella_wrapper tglobaladdr:$dst))),
  (PseudoSW GPR:$src, R0, tglobaladdr:$dst)
>;

R0 is a constant register = 0.

The 3 patterns have in common the fact that zero must be moved into R14.

For the first pattern (PseudoBNE): is it possibile to transform the dag from 

(brcond GPR:$cond, bb:$imm)

to:

(brcond (i16 (setne GPR:$cond, 0)), bb:$imm) ?

In that way the BNE instruction would be selected automatically. The same for the other two, I’d just need to convert:

(store GPR:$src, (i16 (isabella_wrapper tglobaladdr:$dst)))

to:

(store GPR:$src, (add 0, (i16 (isabella_wrapper tglobaladdr:$dst)))

I also tried to do:

def : Pattern<
  (brcond GPR:$cond, bb:$imm),
  [
    (set R14, 0),
    (BNE GPR:$cond, imm16bb:$imm)
  ]
>;

Unfortunately since R14 is not directly used by BNE, TableGen complains about temporaries not supported.

Thanks for all the help.

Marco Speziali
Reply all
Reply to author
Forward
0 new messages