Hi,
I’m trying to replace a shift left instruction with multiple add instructions in LLVM’s RISCV backend, since my target RISCV processor might not contain an implementation of the shift left instruction. (This question is a follow-on to this one.)
For example:
sll x5, x5, x6
should be replaced by
blez x6, .end
.loop:
addi x6, x6, -1
add x5, x5, x5
bnez x6, .loop
.end:
# next instruction
However, I’m struggling to create a branch instruction. Here’s what I have so far (specific questions are in the code comments).
In RISCVTargetLowering::RISCVTargetLowering
:
setOperationAction(ISD::SHL, MVT::i32, Custom);
In RISCVTargetLowering::LowerOperation
:
case ISD::SHL:
return replaceShlWithAdd(Op, DAG);
And
SDValue RISCVTargetLowering::replaceShlWithAdd(SDValue Op, SelectionDAG &DAG) const {
SDLoc DL(Op);
SDValue finalReplacement;
SDValue num = Op.getOperand(0);
SDValue shamtOp = Op.getOperand(1);
EVT VT = num.getValueType();
if (DAG.isConstantIntBuildVectorOrConstantInt(shamtOp)) {
// Already solved in https://discourse.llvm.org/t/replacing-instruction-with-multiple-substitute-instructions/72612
}
else {
SDValue zero = DAG.getConstant(0, DL, VT);
SDValue minusOne = DAG.getConstant(-1, DL, VT);
SDValue ccle = DAG.getCondCode(ISD::SETOLE);
SDValue ccgt = DAG.getCondCode(ISD::SETOGT);
// How do I put these two instructions into an SDValue that corresponds to a basic block?
num = DAG.getNode(ISD::ADD, DL, VT, num, num);
shamtOp = DAG.getNode(ISD::ADD, DL, VT, shamtOp, minusOne);
// I have no idea how to set chain, exitBlock or loopStart
SDValue br0 = DAG.getNode(ISD::BR_CC, DL, VT, chain, ccle, shamtOp, zero, exitBlock);
SDValue br1 = DAG.getNode(ISD::BR_CC, DL, VT, chain, ccgt, shamtOp, zero, loopStart);
// Not sure if this should be set to br1, br0, or something else
finalReplacement = br1;
}
return finalReplacement;
}
Let me know if any further details are required.
Thank you.