LLVM: Customize your Instructions.

For the past few weeks, I was given a task by my supervisor. The task sound simple, whenever there NOP (No operation) instruction will be use, LLVM should change it into XOR R0, R0, R0 which basically doing nothing since in aeMB, register zero (R0) always have zero values.

NOP –change to–> XOR R0, R0, R0

So I start digging. First I look into *InstrInfo.td because thats where all target specific instructions were define. And the tablegen will automatically generate those instructions and parse it to the big boys LLVM for optimization.

I thought that was a correct place to look into. Well, not thought, I was highly confident that IS the place. There were 3 lines of NOP definition.

let neverHasSideEffects = 1 in {
     def NOP : aeMBInst< 0x20, FC,(outs),(ins),"nop",[],IIAlu>;
}

aeMBInst is the generic class of NOP defined inside aeMBInstrFormat.td. It is also called generic aeMB format. The first parameter (0x20) is the opcode, the second parameter (outs) is the output destination and (ins) is the input source, the fourth parameter (“nop”) is a string that is used by the assembly printer, the fifth parameter is list of pattern which is none for NOP and lastly (IIAlu) is the instruction class.

I figure lets change this definition into something similar to XOR. That was easy.

let neverHasSideEffects=1 in {
     def NOP : Logic< 0x22, 0x000, "xor ", xor>;
}

Done. Then I test it, it come out in the assembly file .s as below.

xor r15, puts, r5

Obviously thats not what I want. I carry on digging into LLVM, still my focus is on that aeMBInstrInfo.td file. For your information, aeMBInstrInfo.td was define mostly from /include/llvm/Target/TargetInstrInfo.h file. I also try this,

let neverHasSideEffects = 1 in {
     def NOP : MBlazeInst {
     let Inst{6-31} = 0;
     }
}

notice that “let Inst{6-31} = 0;”, here what I did is set bit 6 until 31 into zero (0) using ‘let’ expression. You may read more about llvm ‘let’ expression here –>Link.

I showed it to my supervisor and he said this is probably more like cheating. Frustrated? yes. Give up? No. Perhaps I should write my custom class of instruction. I wrote it. But still failed. This is after two weeks already.

I almost give up, really. I don’t know where else I should look into. Then suddenly I realized that maybe I was asking the wrong question for all these times! Instead of trying to change the instruction definition as a whole, I should ask myself, how can I make this specific NOP instruction pick only register R0? Well, it may sound the same question as before but this time, it is more specific.

So, I went into #llvm irc channel and ask. There I know that aeMBInstrInfo.td in just a shortcut for assembler. The real place I have to look into are aeMBISelLowering.cpp (interfaces aemb uses to lower LLVM code into selectionDAG) and aeMBSelDAGtoDAG.cpp (manual selection case of aeMB instructions ).

The definition of aeMBISelLowering is of TargetLowering class and aeMBISelDAGtoDAG is of file include/llvm/Target/TargetSelectionDAG.td.

In aeMBSelDAGtoDAG.cpp, there I can actually hand pick any registers I want each instruction to use. Like the examples by ARM and X86. In aeMBISelLowering.cpp, inside this file, there is a function to *expand* or *promote* the code that don’t have native support. Expand when an operation without native support, a combination of other operations may be used to similar effect. Promote when for an operation without native support for a given type, the specified type may be promoted to a larger type that is supported.

example:-

setOperationAction(ISD::FSIN, MVT::f32, Expand);
setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);

Read further here. (link). There you may notice there are also *custom*, in case promotion or operation expansion may be insufficient, and in this situation special function must be implemented.

I wouldn’t say yeay yet for now by knowing this, I definitely has lot more to learn.

 

You may also like...

3 Responses

  1. trekker says:

    Thanks for sharing your experience with LLVM, I am currently writing a backend for a proprietary uP and have experienced similar frustration. I read that the desire for future LLVM releases will offload more of this in the .td files.

  2. Shaiful Taher says:

    Hi trekker,

    Thank you for your comment. I wish you all the best with your task.

    By the way, have you finish it?

  3. acccel says:

    How did you fix your issue at last?

Leave a Reply

Your email address will not be published. Required fields are marked *