Creating tablegen patterns for intrinsics with no return value.

I have intrinsic with no return value and I need to match them to machine instructions. If the instruction has a return value I am able to correctly match it, but if I try to create some tablegen code that has no return value, the instruction gets deleted.

Here is my profile/node/pattern.

Profile:

def SDTIL_BinAtomNoRet : SDTypeProfile<0, 3, [

SDTCisPtrTy<0>, SDTCisVT<1, i32>, SDTCisVT<2, i32>

]>;

Node:

def atom_g_add_noret : SDNode<“AMDILISD::ATOM_G_ADD_NORET”, SDTIL_BinAtomNoRet, [SDNPHasChain]>;

Pattern:

def ATOM_G_ADD_NORET : BinAtomNoRet<IL_OP_UAV_ADD,

“_id($id)”, atom_g_add_noret>;

I am Lowering INTRINSIC_W_CHAIN to lower from @llvm.amdil.atomic.add.gi32.noret to the correct instruction with the following code sequence.

LowerINTRINSIC_W_CHAIN(…)

{

case AMDILIntrinsic::AMDIL_atomic_add_gu32_noret:

IntNo = AMDILISD::ATOM_G_ADD_NORET; break;

SDValue Ops[6];

SDValue chain = Op.getOperand(0);

unsigned numNodes = 0;

if (inChain) {

Ops[numNodes++] = chain;

}

SDValue Chain = Op.getOperand(0);

Ops[numNodes++] = Op.getOperand((inChain) ? 2 : 1);

Ops[numNodes++] = DAG.getConstant(1, MVT::i32);

Ops[numNodes++] = DAG.getTargetConstant(0, MVT::i32);

Op = DAG.getNode(IntNo, dl, EVT::EVT(MVT::i32), Ops, numNodes);

if (outChain) {

SDValue mv[2] = {Op, chain};

Op = DAG.getMergeValues(mv, 2, dl);

}

return Op;

}

I’m guessing I am not handling the chain correctly, but I’m not sure what I am doing wrong. Can someone point me to an example of matching an intrinsic to a machine instruction with no return value?

Thanks,

Micah

I have intrinsic with no return value and I need to match them to machine instructions. If the instruction has a return value I am able to correctly match it, but if I try to create some tablegen code that has no return value, the instruction gets deleted.

Hi Micah,

From your description it sounds like machine dead code elimination is the most likely what's deleting your instruction. If that's the case, adding "let hasSideEffects = 1" to your instruction pattern should suffice to tell the compiler that there's more going on than it can detect just by looking at the inputs and outputs, and so it won't delete the instruction. Something like the following should do the trick:

let hasSideEffects = 1 in
def ATOM_G_ADD_NORET : BinAtomNoRet<IL_OP_UAV_ADD,
      "_id($id)", atom_g_add_noret>;

For an existing example, have a look at the memory barrier instruction definitions for the ARM target (DMB and DMB_MCR in ARMInstrInfo.td).

Regards,
  Jim

From: Jim Grosbach [mailto:grosbach@apple.com]
Sent: Monday, November 08, 2010 10:41 AM
To: Villmow, Micah
Cc: LLVM Developers Mailing List
Subject: Re: [LLVMdev] Creating tablegen patterns for intrinsics with
no return value.

> I have intrinsic with no return value and I need to match them to
machine instructions. If the instruction has a return value I am able
to correctly match it, but if I try to create some tablegen code that
has no return value, the instruction gets deleted.

Hi Micah,

From your description it sounds like machine dead code elimination is
the most likely what's deleting your instruction. If that's the case,
adding "let hasSideEffects = 1" to your instruction pattern should
suffice to tell the compiler that there's more going on than it can
detect just by looking at the inputs and outputs, and so it won't
delete the instruction. Something like the following should do the
trick:
let hasSideEffects = 1 in
def ATOM_G_ADD_NORET : BinAtomNoRet<IL_OP_UAV_ADD,
      "_id($id)", atom_g_add_noret>;

For an existing example, have a look at the memory barrier instruction
definitions for the ARM target (DMB and DMB_MCR in ARMInstrInfo.td).

Regards,
  Jim

[Villmow, Micah] Jim, Thanks for the hint, but I tried that and the instructions still get deleted. I also set let mayStore = 1 and the same issue shows up. I believe the issue is with the ch not being propogated correctly.
I've attached a before and after instruction creation of DAG.dump().

This is the instruction I'm trying to match:
        0x8502b88: i32,ch = llvm.AMDIL.atomic.add.gi32.noret 0x8502a78, 0x8502b00, 0x8502280, 0x8502eb8 [ORD=6] [ID=19]

And I generate this instruction:
0x8503160: i32 = AMDILISD::ATOM_G_ADD_NORET 0x8502a78, 0x8502280, 0x8502eb8, 0x8502f40
    0x8502a78: <multiple use>
  0x8503608: i32,ch = merge_values 0x8503160, 0x8502a78

What I'm trying to figure out is how I can generate this without the merge_values:
0x8503160: i32,ch = AMDILISD::ATOM_G_ADD_NORET 0x8502a78, 0x8502280, 0x8502eb8, 0x8502f40

I probably have other issues, but solving this should help me solve other issues.
Thanks again,
Micah

dag.dump (6.65 KB)

I think I found the problem. Instead of passing just MVT::i32 as the type, I created a SDVTList of MVT::i32 and MVT::Other and now the i32,ch shows up in the DAG output.

Micah