Backend port: Adding negative immediates


I'm doing a backend port and I'm having trouble with adds that have
negative immediates.
My architecture only has instructions for subtracting and adding 8bit
immediate values (they will be zero-extended, thus unsigned).
Bigger immediates have to be moved in a register first.

The problem is:
Expressions like "b - 1" result in "add nsw i32 %b, -1" in LLVM IR.
They cannot be matched to the 8bit unsigned immediate add during
Instruction Selection and will eventually be moved in a register.
It would be better to transform these adds with small negative
immediates into subs during Target Lowering.

So I tried to custom lower ISD::ADD in IselLowering:

MxmTargetLowering::MxmTargetLowering(TargetMachine &TM)
  : TargetLowering(TM, new TargetLoweringObjectFileELF()) {
setOperationAction(ISD::ADD, MVT::i32, Custom);

//check for immediate adds with constant values -256 < x < 0 and
transform them
//to sub
SDValue MxmTargetLowering::LowerADD(SDValue Op, SelectionDAG &DAG) const {
    SDValue Op0 = Op.getOperand(0);
    SDValue Op1 = Op.getOperand(1);

    if(ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1)) {
        int val = CN->getSExtValue();
        if(val < 0 && val > -256) {
            return DAG.getNode(ISD::SUB, dl, MVT::i32,
                Op0,DAG.getConstant(-val, MVT::i32));
    return Op;

SDValue MxmTargetLowering::
LowerOperation(SDValue Op, SelectionDAG &DAG) const {

    switch(Op.getOpcode()) {
        case ISD::GlobalAddress:
            return LowerGlobalAddress(Op, DAG);
        case ISD::ConstantPool:
            return LowerConstantPool(Op,DAG);
        case ISD::ADD:
            return LowerADD(Op,DAG);
            llvm_unreachable("illegal custom lowering operation");

Unfortunately, this has absolutely no effect. The resultig ISel-DAG has
still the adds with negative immediates.
Maybe I'm doing it completely wrong. Could anyone give me some advice
with that?

Jan Tlatlik

Instead of trying to handle this during target lowering you can add a pattern to your that matches the add node with a negative immediate. In the XCore backend the SUB_2rus instruction takes an immediate in the range 0-11 and this is handled by the following pattern:

// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
def : Pat<(add GRRegs:$src1, immUsNeg:$src2),
          (SUB_2rus GRRegs:$src1, (neg_xform immUsNeg:$src2))>;

Where immUsNeg and neg_xform are defined as follows:

def immUsNeg : PatLeaf<(imm), [{
  return -((uint32_t)N->getZExtValue()) <= 11;

def neg_xform : SDNodeXForm<imm, [{
  // Transformation function: -imm
  uint32_t value = N->getZExtValue();
  return getI32Imm(-value);