Immediate operand for load instruction, in back end

Hello,
     I'm trying to define in my new back end, in MyBackendInstrInfo.td file, a vector load instruction that takes an immediate address operand. (I got inspired from Mips' MSA SIMD extensions.)
     Could you please tell me what's the right way to do it?

     Here, the load class has $addrsrc which is a relative address with base a certain register and offset:
class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
     ValueType TyNode, RegisterOperand ROWD,
     Operand MemOpnd = mem_msa,
     ComplexPattern Addr = addrimm10,
     InstrItinClass itin = NoItinerary> {
   dag OutOperandList = (outs ROWD:$wd);
   dag InOperandList = (ins MemOpnd:$addrsrc);
   string AsmString = !strconcat("mov $wd, ($addrsrc)");
   list<dag> Pattern = [(set ROWD:$wd, (TyNode (OpNode Addr:$addrsrc)))];
   InstrItinClass Itinerary = itin;
   string DecoderMethod = "DecodeMSA128Mem";
}

class LD_D_DESC : LD_DESC_BASE<"ldvd", load, v32i16, MSA128DOpnd>;

    I've tried to change mem_msa to hold only let MIOperandInfo = (ops simm10) but there are problems it seems:

// MSA specific address operand
def mem_msa : mem_generic {
let MIOperandInfo = (ops ptr_rc, simm10);
let EncoderMethod = "getMSAMemEncoding";
}

    Could you please tell me what is the simplest way to define in LD_DESC_BASE a $addrsrc that is just an immediate value like i16 or i16imm?

   Thank you very much,
     Alex

Hi Alex,

So far, the code you've mentioned only defines a couple tablegen classes but doesn't define the instruction itself. To define the instruction you will also need a 'def' statement. For MIPS MSA, this statement looks like this:
    def LD_D: LD_D_ENC, LD_D_DESC;
This defines an instruction (LD_D) with the encoding specified by the LD_D_ENC class, and the operation description (including assembly syntax) specified by the LD_D_DESC class. You'll sometimes find 'adjectives' like ISA_MIPS2 which specify the version of the MIPS architecture in which the instruction is available. We don't need one here because all the MSA instructions specify the MSA requirement in one of the base classes of LD_D_ENC.

For CodeGen support, you will also need to make changes to ${TARGET}ISelLowering.cpp (MipsSEISelLowering.cpp for MIPS). The relevant code for MIPS is in addMSAIntType() and addMSAFloatType() and makes the vector types legal by binding them to a register class and specifies how to handle each operation using setOperationAction().

    I've tried to change mem_msa to hold only let MIOperandInfo = (ops
simm10) but there

It sounds like you're on the right track but there may be an easier way. Continuing on this track, I believe you will also need to change the addrimm10 mentioned in the argument list for LD_DESC_BASE. The one for MIPS will be matching the DAG using the selectIntAddrMSA() function which will produce the two operands expected by mem_msa.

I haven't tried this but given that you only want an immediate address, it may be easier to use an immediate operand (e.g. uimm4_ptr, you may need to search for 'uimm # I # _ptr' for the definition) and an ImmLeaf subclass (e.g. immZExt4Ptr) instead of the mem_msa and addrimm10.

Hope this helps

Hello.
     Daniel, I was able to fix my back end following your advice and writing special LLVM IR code, normally not generated by clang or opt (I have to do so, since my SIMD research processor has it's own local memory, separate from the CPU memory).

     I've managed to solve the issue with the MemOperand suggested in the previous email, below.

     In case this interests others, I'll be a bit more precise. Suppose I have the following .ll file to compile with llc, with immediate address operands for load (and store):
       ; ModuleID = '3better.ll'
       target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
       target triple = "x86_64-unknown-linux-gnu"

       ; Function Attrs: norecurse nounwind readonly uwtable
       define i64 @foo(i64* nocapture readnone %A, i64* nocapture readnone %B, i64* nocapture readnone %C, i64 %N) #0 {
        entry:
         %wide.load = load <8 x i64>, <8 x i64>* inttoptr (i64 4161 to <8 x i64>*), align 4

         %Cptr = getelementptr inbounds i64, i64* %C, i64 0
         %Cptr_vec = bitcast i64* %Cptr to <8 x i64>*
         store <8 x i64> %wide.load, <8 x i64>* %Cptr_vec, align 4
         ;store <8 x i64> %wide.load, <8 x i64>* inttoptr (i64 5000 to <8 x i64>*), align 4

         %res = load i64, i64* inttoptr (i64 5000 to i64*), align 4
         ;%res = load i64, i64* %Cptr, align 4
         ret i64 %res
       }

       !0 = !{!"clang version 3.8.0 (trunk 253324)"}

  In the InstrInfo.td file I wrote:
   def immLeafAlex : ImmLeaf<i64, [{return 1;}]>;
   def uimm4_ptr : Operand<iPTR> {
     let PrintMethod = "printUnsignedImm";
   }

   class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
                    ValueType TyNode, RegisterOperand ROWD,
                    Operand MemOpnd = uimm4_ptr,

                    ImmLeaf Addr = immLeafAlex,
                    InstrItinClass itin = NoItinerary> {
     dag OutOperandList = (outs ROWD:$wd);
     dag InOperandList = (ins MemOpnd:$addrsrc);
     string AsmString = !strconcat("$wd = LocalMem[$addrsrc]", instr_asm);

     list<dag> Pattern = [(set ROWD:$wd, (TyNode (OpNode Addr:$addrsrc)))];
     InstrItinClass Itinerary = itin;
     string DecoderMethod = "DecodeMSA128Mem";
   }
   // similarly: class ST_DESC_BASE

   The new llc built with the above TableGen description is able to compile the above LLVM program correctly.

   Best regards,
     Alex