SelectionDAG

Hello,
  I am working on a AVR backend and have a version up and running that will convert LLVM IR code to assembly code for my target. I have written a bunch of instructions from the AVR Instruction Set in AVRInstrInfo.td and not much else. In a simple test case I am attempting to compile (if that is the word you are supposed to use for this operation) test.ll:

define i8 @foo(i8 %a, i8 %b) {
entry:
  %c = sub i8 %a, 5
  ret i8 %c
}

with `build/Debug/bin/llc -march=avr llvm.ll -o -` and I receive:

  .file "test.ll"
  .text
  .global foo
  .type foo,@function
foo: # @foo
# BB#0: # %entry
  MOV r22, r24
  LDI r24, -5
  ADD r24, r18
  RET
.tmp0:
  .size foo, .tmp0-foo

While I would like the output as such:

  .file "test.ll"
  .text
  .global foo
  .type foo,@function
foo: # @foo
# BB#0: # %entry
  SUB r24, 5
  RET
.tmp0:
  .size foo, .tmp0-foo

With that my question is how to get LLVM to select SUB instead of the pattern above. I have tried to place SUB8ri (see below) before the ADD8rr instruction in the .td file, but that does not seem to make a difference. *things to note, the AVR instruction set does not contain a ADD8ri, so I would eventually like to convert all add register and immediate to subtract register and -immediate, but for now if I could just get LLVM to use SUB8ri in the most straightforward case that would work for me. Thanks,
  Joshua

// SUB8ri definition
let Constraints = "$src = $dst" in
def SUB8ri : Instruction {
  let Namespace = "AVR";
  dag OutOperandList = (outs GPR8:$dst);
  dag InOperandList = (ins GPR8:$src, i8imm:$src2);
  let AsmString = "SUB\t{$dst, $src2}";
  let Pattern = [(set GPR8:$dst, (opnode GPR8:$src, imm:$src2))];
}

Joshua Nedrud
Master of Science, Biomedical Engineering

Joshua,

You can achieve this through the use of SDNodeXForm and Pat's. Here's a snippet to get your started.

def imm_neg_XFORM : SDNodeXForm<imm, [{
  return CurDAG->getTargetConstant(-N->getSExtValue(), MVT::i8);
}]>;
def imm0_255_neg : PatLeaf<(i8 imm), [{
  unsigned Val = N->getZExtValue();
  return Val > 0 && Val < 256;
}], imm_neg_XFORM>;

def : Pat<(add GPR8:$src1, imm0_255_neg:$src2),
                 (SUB8ri GPR8:$src1, imm0_255_neg:$src3)>;

--Owen