Immediate operand for vector instructions

Hello.
     I have problems specifying vector instructions with immediate values in TableGen.

     I wrote the following specification (I got inspired from the MSA vector instructions for the Mips back end):
         class MSA_I16_FMT<bits<9> opcode>: MSAInst {
           bits<16> s16;
           let Inst{31-23} = opcode;
           let Inst{26-11} = s16;
         }
         class REP_1R_DESC_BASE<,
                                     InstrItinClass itin = NoItinerary> {
           dag OutOperandList = (outs);
           /* From include/llvm/Target/Target.td:
              let OperandType = "OPERAND_IMMEDIATE" in {
                ...
              def i64imm : Operand<i64>; */
           dag InOperandList = (ins i64imm:$imm);

           string AsmString = "REPEAT_X_TIMES($imm";
           list<dag> Pattern = [(int_repeat_x_times i64imm:$imm)];
           InstrItinClass Itinerary = itin;
         }
         class REP_D_DESC : REP_1R_DESC_BASE;
         class REP_D_ENC : MSA_I16_FMT<0b101010111>;
         def REP_D: REP_D_ENC, REP_D_DESC;

     and added in the LLVM program (programmatically, in an LLVM pass) an LLVM IR repeat_x_times intrinsic.
     To my big surprise (because of the property OperandType = "OPERAND_IMMEDIATE"), the resulting ASM codegen'ed by the instruction selector contains a mov and use a register:
         mov r1, 32767 // <MCInst #75 MOV_ri
                                         // <MCOperand Reg:2>
                                         // <MCOperand Imm:32767>>
         REPEAT_X_TIMES(r1);
         ...

     Note that in the end I managed to fix this problem by using an address operand as immediate operand (inspired again from Mips MSA vector instructions), but I consider this a somewhat strange solution:
         class REP_1R_DESC_BASE<Operand MemOpnd = uimm4_ptr,
                                 ImmLeaf Addr = immLeaf,
                                 InstrItinClass itin = NoItinerary> {
           dag OutOperandList = (outs);
           dag InOperandList = (ins MemOpnd:$addrdst);

           string AsmString = "REPEAT_X_TIMES($addrdst );";
           list<dag> Pattern = [(int_connex_repeat_x_times Addr:$addrdst)];
           InstrItinClass Itinerary = itin;
         }

     So, is there are way to use immediate values that are not memory operands?

   Thank you ,
     Alex

i64imm isn't usable in patterns by default, so what have you really
written? The operand should probably be "imm:$imm", and "i64:$imm"
definitely gives the behaviour you're describing.

Cheers.

Tim.

Hello.
     Tim, indeed the TableGen spec I presented in the previous email has a small error related to what you have written - the patter does not allow i64imm. So because of the line:
   list<dag> Pattern = [(int_connex_repeat_x_times i64imm:$imm)];
     I get the following TableGen error:
    <<Unknown leaf kind: i64imm:i64:$imm>>

      But if I correct that error, following also your suggestion, and have the following code (reproduced for convenience):
          class REP_1R_DESC_BASE<,
                                      InstrItinClass itin = NoItinerary> {
            dag OutOperandList = (outs);
            /* From include/llvm/Target/Target.td:
               let OperandType = "OPERAND_IMMEDIATE" in {
                 ...
               def i64imm : Operand<i64>; */
            dag InOperandList = (ins i64imm:$imm);

            string AsmString = "REPEAT_X_TIMES($imm";
            list<dag> Pattern = [(int_repeat_x_times i64:$imm)];
            InstrItinClass Itinerary = itin;
          }
          class REP_D_DESC : REP_1R_DESC_BASE;
          class REP_D_ENC : MSA_I16_FMT<0b101010111>;
          def REP_D: REP_D_ENC, REP_D_DESC;

    We can compile it. Note that this is the only compilable code w.r.t. using i64 or i64imm (in the 2 lines above: "dag InOperandList", "list<dag> Pattern").

     However, the problem I was asking help in the previous email still persists: to my big surprise (because the property OperandType = "OPERAND_IMMEDIATE" implies that i64imm is an immediate operand), the resulting ASM codegen'ed by the instruction selector contains a mov and REPEAT_X_TIMES uses a register although I was expecting it to use an immediate register:
          mov r1, 32767 // <MCInst #75 MOV_ri
                                          // <MCOperand Reg:2>
                                          // <MCOperand Imm:32767>>
          REPEAT_X_TIMES(r1);
          ...

   Best regards,
     Alex

Hi Alex,

   We can compile it. Note that this is the only compilable code w.r.t.
using i64 or i64imm (in the 2 lines above: "dag InOperandList", "list<dag>
Pattern").

Yeah, you actually want to use "imm":

    list<dag> Pattern = [(int_repeat_x_times imm:$imm)];

When the table generator sees "i64" it doesn't go looking in the
InOperandList to determine that the operand should be an immediate. It
just matches anything and shoves it into a register. It *does* know
about "imm" though because that's defined to match up to an
ISD::Constant SDNode.

Cheers.

Tim.

Hello.
     Tim, thank you for the observations. This is the one thing that I haven't tried in the previous email :slight_smile: . So the complete correct specification is:
       class REPEAT_DESC_BASE<InstrItinClass itin = NoItinerary> {
         dag OutOperandList = (outs);
         dag InOperandList = (ins i64imm:$imm);
         string AsmString = "REPEAT_X_TIMES($imm );";
         list<dag> Pattern = [(int_connex_repeat_x_times imm:$imm)];
         bit hasSideEffects = 1;
         InstrItinClass Itinerary = itin;
       }

     Although not relevant I guess, these were the error messages I got when using different types:
         - <<Unknown leaf kind: i64imm:i64:$imm>>
           when using:
             list<dag> Pattern = [(int_connex_repeat_x_times i64imm:$imm)];
         - <<error:Unknown operand class 'imm' in 'REPEAT_D' instruction!>>
           when using:
             dag InOperandList = (ins i64imm:$imm);

   Best regards,
     Alex