[llvm-dev] Tablegen pattern: How to emit a SDNode in an output pattern?

via llvm-dev llvm-dev at lists.llvm.org
Mon Apr 9 10:15:59 PDT 2018



> On Apr 9, 2018, at 1:17 AM, Max Muster via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> 
> I'm trying to write a tablegen pattern to that matches a sequence of SDNodes and emits again an SDNode and another instruction.
> The pattern I've written looks like the folowing:
> 
> def : Pat<(foo (bar GPR:$rs1), simm12:$imm1), 
>           (bar (BAZ GPR:$rs1, simm12:$imm1))>;
> 
> foo and bar are SDNodes, BAZ is an instruction. In particular, bar is defined as follows:
> 
> def bar : SDNode<"ISD::BAR", SDTIntUnaryOp>;
> 
> The basic idea of this pattern is to propagate bar over certain instructions until they reach a sink pattern, which only emits an instruction.
> However, it seems that SDNodes in output patterns are not supported, because when building LLVM, I get the following error message:
> 
> error: In anonymous_826: Cannot use 'bar' in an output pattern!
> 
> What are the limits of tablegen here?
> What are alternatives to propagate the bar node over instructions to reach the same behavior is the pattern-based approach?
> 
> Thank you in advance!

Firstly, are you sure you can’t do this in combine() or in preprocessiseldag()? Most of the time you may find it better to do things there (we use the latter for cases where the optimization may interfere with DAG canonicalization, and so we need to do it late).

Secondly, if you do need to do it in Select(), you can write custom C++ code in Select() for that purpose. It gets a little finicky because you will have to reposition the new DAG nodes you create in order to put them in order. For example, see the following function:

inline void InsertDAGNode(SelectionDAG &DAG, SDValue Pos, SDValue N) {
  if (N->getNodeId() == -1 ||
      (SelectionDAGISel::getUninvalidatedNodeId(N.getNode()) >
       SelectionDAGISel::getUninvalidatedNodeId(Pos.getNode()))) {
    DAG.RepositionNode(Pos->getIterator(), N.getNode());
    // Mark Node as invalid for pruning as after this it may be a successor to a
    // selected node but otherwise be in the same position of Pos.
    // Conservatively mark it with the same -abs(Id) to assure node id
    // invariant is preserved.
    N->setNodeId(Pos->getNodeId());
    SelectionDAGISel::InvalidateNodeId(N.getNode());
  }
}

I have no idea how “bad” this is, but we use it internally.

—escha



More information about the llvm-dev mailing list