[LLVMdev] Porting LLVM backend is no fun yet
Chris Lattner
clattner at apple.com
Mon Apr 13 11:20:09 PDT 2009
On Apr 13, 2009, at 11:05 AM, Vladimir Prus wrote:
> Dan Gohman wrote:
>
>> There certainly are wishlist items for TableGen and TableGen-based
>> instruction descriptions, though I don't know of an official list.
>> Offhand,
>> a few things that come to mind are the ability to handle nodes with
>> multiple results,
>
> Is there an official workaround, BTW?
Currently you have to write C++ code. See how the X86 backend handles
mul hi/lo instructions, for example:
case ISD::SMUL_LOHI:
case ISD::UMUL_LOHI: {
SDValue N0 = Node->getOperand(0);
SDValue N1 = Node->getOperand(1);
bool isSigned = Opcode == ISD::SMUL_LOHI;
if (!isSigned)
switch (NVT.getSimpleVT()) {
default: assert(0 && "Unsupported VT!");
case MVT::i8: Opc = X86::MUL8r; MOpc = X86::MUL8m; break;
case MVT::i16: Opc = X86::MUL16r; MOpc = X86::MUL16m; break;
case MVT::i32: Opc = X86::MUL32r; MOpc = X86::MUL32m; break;
case MVT::i64: Opc = X86::MUL64r; MOpc = X86::MUL64m; break;
}
else
switch (NVT.getSimpleVT()) {
default: assert(0 && "Unsupported VT!");
case MVT::i8: Opc = X86::IMUL8r; MOpc = X86::IMUL8m; break;
case MVT::i16: Opc = X86::IMUL16r; MOpc = X86::IMUL16m; break;
case MVT::i32: Opc = X86::IMUL32r; MOpc = X86::IMUL32m; break;
case MVT::i64: Opc = X86::IMUL64r; MOpc = X86::IMUL64m; break;
}
unsigned LoReg, HiReg;
switch (NVT.getSimpleVT()) {
default: assert(0 && "Unsupported VT!");
case MVT::i8: LoReg = X86::AL; HiReg = X86::AH; break;
case MVT::i16: LoReg = X86::AX; HiReg = X86::DX; break;
case MVT::i32: LoReg = X86::EAX; HiReg = X86::EDX; break;
case MVT::i64: LoReg = X86::RAX; HiReg = X86::RDX; break;
}
SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
bool foldedLoad = TryFoldLoad(N, N1, Tmp0, Tmp1, Tmp2, Tmp3,
Tmp4);
// multiplty is commmutative
if (!foldedLoad) {
foldedLoad = TryFoldLoad(N, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
if (foldedLoad)
std::swap(N0, N1);
}
SDValue InFlag = CurDAG->getCopyToReg(CurDAG->getEntryNode(),
dl, LoReg,
N0,
SDValue()).getValue(1);
if (foldedLoad) {
SDValue Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
N1.getOperand(0),
InFlag };
SDNode *CNode =
CurDAG->getTargetNode(MOpc, dl, MVT::Other, MVT::Flag, Ops,
array_lengthof(Ops));
InFlag = SDValue(CNode, 1);
// Update the chain.
ReplaceUses(N1.getValue(1), SDValue(CNode, 0));
} else {
InFlag =
SDValue(CurDAG->getTargetNode(Opc, dl, MVT::Flag, N1,
InFlag), 0);
}
// Copy the low half of the result, if it is needed.
if (!N.getValue(0).use_empty()) {
SDValue Result = CurDAG->getCopyFromReg(CurDAG-
>getEntryNode(), dl,
LoReg, NVT, InFlag);
InFlag = Result.getValue(2);
ReplaceUses(N.getValue(0), Result);
#ifndef NDEBUG
DOUT << std::string(Indent-2, ' ') << "=> ";
DEBUG(Result.getNode()->dump(CurDAG));
DOUT << "\n";
#endif
}
// Copy the high half of the result, if it is needed.
if (!N.getValue(1).use_empty()) {
SDValue Result;
if (HiReg == X86::AH && Subtarget->is64Bit()) {
// Prevent use of AH in a REX instruction by referencing AX
instead.
// Shift it down 8 bits.
Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
X86::AX, MVT::i16, InFlag);
InFlag = Result.getValue(2);
Result = SDValue(CurDAG->getTargetNode(X86::SHR16ri, dl,
MVT::i16,
Result,
CurDAG->getTargetConstant(8,
MVT::i8)), 0);
// Then truncate it down to i8.
SDValue SRIdx = CurDAG->getTargetConstant(X86::SUBREG_8BIT,
MVT::i32);
Result = SDValue(CurDAG->getTargetNode(X86::EXTRACT_SUBREG,
dl,
MVT::i8, Result,
SRIdx), 0);
} else {
Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
HiReg, NVT, InFlag);
InFlag = Result.getValue(2);
}
ReplaceUses(N.getValue(1), Result);
#ifndef NDEBUG
DOUT << std::string(Indent-2, ' ') << "=> ";
DEBUG(Result.getNode()->dump(CurDAG));
DOUT << "\n";
#endif
}
#ifndef NDEBUG
Indent -= 2;
#endif
return NULL;
More information about the llvm-dev
mailing list