Hi,
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);
default:
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
On 25 Mar 2013, at 00:16, Jan Tlatlik <jtlatlik at techfak.uni-bielefeld.de> wrote:> Hi, > > 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.Instead of trying to handle this during target lowering you can add a pattern to your InstructionInfo.td 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); }]>;
Possibly Parallel Threads
- Backend subtraction changed to negative addition
- [LLVMdev] adjust address calculus for an architecture that does not address bytes
- [LLVMdev] adjust address calculus for an architecture that does not address bytes
- add intrinsic function support for customized backend
- Experimental 6502 backend; memory operand folding problem