[LLVMdev] understanding DAG: node creation

Dmitri Kovalenko dmitri.a.kovalenko at gmail.com
Mon Sep 1 07:39:48 PDT 2014


Yes, I'm going to provide it. I believe there must be no additional work on
the scheduling phase. It's just some mistake in the instruction definition
or DAG.

I create Nodes inside SelectionDAGBuilder::visitIntrinicCall like that:

  case Intrinsic::sparc_xmac: {
    SDVTList nodeTys = DAG.getVTList(MVT::Other, MVT::i32);
    SDValue Ops[3];
    Ops[0] = getRoot();
    Ops[1] = getValue(I.getArgOperand(0));
    Ops[2] = getValue(I.getArgOperand(1));
    SDValue xmacCall = DAG.getNode(ISD::XMAC, sdl, nodeTys, Ops);
    DAG.setRoot(xmacCall.getValue(0));
    return nullptr;
  }
  case Intrinsic::sparc_srxacc: {
    SDVTList nodeTys = DAG.getVTList(MVT::Other, MVT::i32);
    SDValue Ops[2];
    Ops[0] = getRoot();
    Ops[1] = getValue(I.getArgOperand(0));
    SDValue srCall = DAG.getNode(ISD::SRXACC, sdl, nodeTys, Ops);
    DAG.setRoot(srCall.getValue(0));
    return nullptr;
  }
  case Intrinsic::sparc_lrxacc: {
    SDVTList nodeTys = DAG.getVTList(MVT::Other,MVT::i32);
    SDValue Ops[1];
    Ops[0] = getRoot();
    SDValue lrCall = DAG.getNode(ISD::LRXACC, sdl,
                                 nodeTys, Ops);
    DAG.setRoot(lrCall.getValue(0));
    setValue(&I, lrCall.getValue(1));
    return nullptr;
  }

Then, lower them trivially.

setOperationAction(ISD::LRXACC, MVT::Other, Legal);
setOperationAction(ISD::SRXACC, MVT::Other, Legal);
setOperationAction(ISD::XMAC, MVT::Other, Legal);

Then, just set respective instr opcodes in SparcDAGToDAGISel::Select:

  case ISD::SRXACC: {
    SDVTList nodeTys = CurDAG->getVTList(MVT::Other);

    SDValue Ops[2];
    Ops[0] = N->getOperand(0);
    Ops[1] = N->getOperand(1);

    return CurDAG->SelectNodeTo(N, SP::SRXACC, nodeTys, Ops);
  }
  case ISD::XMAC: {
    SDVTList nodeTys = CurDAG->getVTList(MVT::Other);

    SDValue Ops[3];
    Ops[0] = N->getOperand(0);
    Ops[1] = N->getOperand(1);
    Ops[2] = N->getOperand(2);

    return CurDAG->SelectNodeTo(N, SP::XMAC, nodeTys, Ops);
  }
  case ISD::LRXACC: {
    SDVTList nodeTys = CurDAG->getVTList(MVT::Other, MVT::i32);
    SDValue Ops[1];
    Ops[0] = N->getOperand(0);
    return CurDAG->SelectNodeTo(N, SP::LRXACC, nodeTys, Ops);
 }

They declared as:
def XMAC : F3_1<2, 0b111111,
                      (outs),
                      (ins IntRegs:$rs1, IntRegs:$rs2),
                      "xmac $rs1, $rs2, %xacc",
                      []>;

let rs1 = 0, rd = 1, Uses=[XACC] in
def LRXACC : F3_1<2, 0b101110,
                 (outs IntRegs:$rd), (ins),
                 "lrxacc %xacc, $rd", []>;

let rd = 0, Defs=[XACC] in
def SRXACC : F3_1<2, 0b011101,
                   (outs), (ins IntRegs:$rs1),
                   "srxacc $rs1, %xacc", []>;

While my register is declared as:
def XACC : Ri<88, "XACC">, DwarfRegNum<[88]>;

Please, note:
My problem is of self-educational and investigative nature.
This instruction srxacc and register xacc are not real.
Produced code aren't supposed to work anywhere.
I just need llc to be able to output assembly file.
Thanks for your insights.


2014-09-01 18:26 GMT+04:00 Sam Parker <S.Parker3 at lboro.ac.uk>:

>  Hi,
> I'm not sure. But in your lowered DAG the chain nodes are the first
> operands for you custom nodes, however for the other nodes the chain is the
> last operand. I seem to remember that during targetlowering the chain is
> the first operand and then it seems to switch over after ISelDAG, this
> confused me and may have something to do with the issue that you are
> seeing. I really don't know much about scheduling, do you want to post your
> instruction definitions again to see if someone else has some ideas,.
>
> cheers,
> sam
>
> Sam Parker
> Research Student
> Electronic System Design Group
> School of Electronic, Electrical and Systems Engineering
> Loughborough University
> UK
>
> On 01/09/14 14:35, Dmitri Kovalenko wrote:
>
>    Before I wrote here, I tried both ways you decsribed, but none of them
> has worked out for me.
>  With yours sugesstions I was able to move a bit further with the first
> approach (when we don't create regclass and just hard-code it in .td)
>
>  But I still receive strange errors. I received DAG which I happy with
> (DAG here: http://goo.gl/62tpkk), but everything goes broken on
> scheduling.
>
>  I had to chain mine nodes, because otherwise nodes xmac and srxacc got
> removed on first combine. But since they are chained, they have MVT::Other
> return type, and that causes strange crash inside func GetCostFor in
> ScheduleDAGRRList.cpp:
>
> Def RegClass = TLI->getRepRegClassFor(VT)->getID();
>  When VT is MVT::Other it returns 0x0, what results crash.
>
>  It got me confused, because reading documentation on CodeGen gave me an
> idea, that chain edges are control flow edges, not data edges. So I don't
> understand why scheduler tries to assign some register to it.
>
>  I'm struggling with this problem way to long for now, and I very
> appreciate yours help, Sam.
>
>
>
>  2014-09-01 1:50 GMT+04:00 Sam Parker <S.Parker3 at lboro.ac.uk>:
>
>> Hi,
>>
>> Yes, that's what I would do. If you want LLVM and the register allocator
>> to also know that the instruction explicitly defines the register, I would
>> designate the register into it's own register class and have your
>> instruction write to that class (and there will be only a single option for
>> RA).
>>
>> cheers,
>> Sam
>>
>> Sam Parker
>> Research Student
>> Electronic Systems Design Group
>>  Loughborough University
>> UK
>>
>> ________________________________________
>> From: Dmitri Kovalenko [dmitri.a.kovalenko at gmail.com]
>> Sent: 31 August 2014 21:53
>> To: Sam Parker
>> Cc: llvmdev at cs.uiuc.edu
>> Subject: Re: [LLVMdev] understanding DAG: node creation
>>
>> Sam, thanks for your answer.
>> That's a great suggestion.
>>
>> And excuse me for maybe dilettante question:
>> To hard-code use of the global register means to hard-code it in the 'asm
>> string' argument of the instruction definition in the .td file?
>>
>>
>>  2014-09-01 0:44 GMT+04:00 Sam Parker <S.Parker3 at lboro.ac.uk<mailto:
>> S.Parker3 at lboro.ac.uk>>:
>> Hi Dmitri,
>>
>> If you have such a simple intrinsic which operates on a single register,
>> just lower the intrinsic to a target specific node which is only
>> implemented by a single instruction. Like you were doing before and by
>> using a chain operand. Hard code the instruction to use and define the
>> global register and only pass the instruction the actual variable argument.
>>
>> Hope that helps,
>> Sam
>>
>> Sam Parker
>> Research Student
>> Electronic Systems Design Group
>> School of Electronic, Electrical and Systems Engineering
>> Loughborough University
>>
>> ----- Reply message -----
>>  From: "Dmitri Kovalenko" <dmitri.a.kovalenko at gmail.com<mailto:
>> dmitri.a.kovalenko at gmail.com>>
>> To: <llvmdev at cs.uiuc.edu<mailto:llvmdev at cs.uiuc.edu>>
>> Subject: [LLVMdev] understanding DAG: node creation
>> Date: Sat, Aug 30, 2014 22:18
>>
>>
>> I have an intrinsic and it must be lowered to instruction, which works
>> with fixed register.
>> So, it takes contents of this register and another argument as input.
>> After execution, the result of the instruction is placed into that same
>> fixed register.
>>
>> What should I do in SelectionDAGBuilder::visitIntrinicCall to describe
>> such behaviour for a SDNode?
>>
>> Thank you for the ideas and insights.
>>
>> --
>> Sincerely,
>> Dmitri Kovalenko
>>
>>
>>
>> --
>> Sincerely,
>> Dmitri Kovalenko
>>
>
>
>
> --
> Sincerely,
> Dmitri Kovalenko
>
>
>


-- 
Sincerely,
Dmitri Kovalenko
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140901/3c6c5419/attachment.html>


More information about the llvm-dev mailing list