[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