Как создать новый SDNode в llvm?

Я пытаюсь добавить поддержку новой арки в бэкэнде llvm (llc). Однако мне было сложно добавить новый SDNode, который имеет 2 результата. Я видел в арке sparc, что UMUL/SMUL имеет 2 результата (второй Y), поэтому они определили:

let Defs = [Y] in {
  defm UMUL : ...
  defm SMUL : ...
}

и

let Uses = [Y], ... in
  def RDY : ...

и в функции выбора это выглядит так:

 SDNode *Mul = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Glue,
                                     MulLHS, MulRHS);
// The high part is in the Y register.
return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDValue(Mul, 1));

поэтому они используют результат 1 - я думаю, это Y...


в моем случае у меня есть инструкция, которая влияет на бит cc. Так что я пытался использовать таким же образом. Я определил в Xinstr:

def SUBCri : ...>{
  let Defs = [CRZ];
}

. .

let Uses = [CRZ] in {
  def BRC_Z : ... (outs), (ins target:$dst),
}

и в функции выбора:

    SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::Glue);
    SDNode * CondCode = CurDAG->getMachineNode(X::SUBCri, dl, VTs, ops);
    SDNode * ResNode = CurDAG->SelectNodeTo(Node, X::BRC_Z, MVT::Other, Dst,
            SDValue(CondCode, 1));

но я получаю следующую ошибку:

Assertion `NumMIOperands >= II.getNumOperands() && NumMIOperands <= II.getNumOperands() + II.getNumImplicitDefs() + NumImpUses && "#operands for dag node doesn't match .td file!"' failed.

поэтому мой вопрос:

  1. как правильно определить SDNode?
  2. что означает SDVTList VTs? Это результаты? что означает порядок (SDVTList VTs)?
  3. что такое OpsArray? это входы? каков правильный порядок вставки ввода? Я видел, что в функции countOperands они проверяют, является ли последний клеем. что значит клей последний? в той же функции они проверяют, существует ли MVT::Other? что это значит ?
  4. и наконец - что я делаю не так? почему я не могу получить второй результат? почему я постоянно получаю эту ошибку?

person yehudahs    schedule 26.09.2015    source источник


Ответы (1)


Это действительно должен быть комментарий, но у меня нет представителя. Некоторые советы, которые, надеюсь, помогут:

  • VT означает тип значения. LLVM должен знать тип(ы) возвращаемых значений каждого SDNode. Передавая VT в getMachineNode, вы создаете новый SDNode, который возвращает столько значений, сколько есть в SDVTList, с указанными типами.

  • «Клей» — это специальный ValueType, который на самом деле не содержит значения. Он просто используется для обеспечения того, чтобы два склеенных SNode не разделялись при планировании инструкций.

  • «ops» действительно являются входными данными.

  • Порядок входных и возвращаемых значений должен точно соответствовать порядку, указанному в TableGen.

  • Я не уверен в этом, но я не думаю, что Defs превращаются в неявные возвращаемые значения. Возможно, вам придется вручную создать узел CopyFromReg, чтобы захватить регистр, в который записывается.

  • MVT::Other представляет собой «цепочку», способ гарантировать, что инструкции с побочными эффектами не будут переупорядочены относительно друг друга.

Прочтите документы doxygen, они довольно хорошо объясняют отдельные функции (даже если немного не хватает общей картины).

Попробуйте начать здесь: http://llvm.org/docs/doxygen/html/classllvm_1_1SelectionDAG.html

person Cheng Sun    schedule 30.09.2015