creating Intrinsic DAG Node

I’m trying to ‘lower’ an operation that needs to create a node in the SD that is an intrinsic call… what is the best way to do this?

I see in the DAGBuilder it calls ‘setValue’ which adds to the map NodeMap[V] where V is the key and the passed in SDValue is the value but I’m not sure this is a good way to do it since these are local to SelectionDAGBuilder and the lowering needs to happen in XXXISelLowering.cpp.

Thanks.

SelectionDAGBuilder creates INTRINSIC_W_CHAIN, INTRINSIC_WO_CHAIN, or INTRINSIC_VOID nodes. You want to emit those with the intrinsic ID as a TargetConstant the first operand (or second with chains). I would recommend though for these cases, if you want to emit emit them in the backend, it’s a bit nicer to lower these to a custom node, and select on that. It’s a bit nicer than having to add the intrinsic ID everywhere. Most of the AMDGPU intrinsics are handled this way.

-Matt

Matt,

Thanks for the response. Is there an example in the code somewhere of doing the intrinsic ID method? I don’t need to put it a lot of places so I’m not sure it warrants adding a node.

Thanks.

Just do a git grep “getNode(ISD::INTRINSIC_WO_CHAIN”. It looks like there are a bunch in AArch64ISelLowering

Matt,

Is this an example you are talking about:

LoadedVect = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f64,
DAG.getConstant(Intrinsic::ppc_qpx_qvfcfidu, dl, MVT::i32),
LoadedVect);

Something like this?

Yes

Matt,

This seems to generate llvm.my_intrinsic just fine in the DAG, so no DAG errors; however, it won’t match. For example, if I call the intrinsic from C, the DAG node looks to be named the same in dotty file but it won’t match… am I missing something?

I’ve done it exactly the way it was done above. The DAG looks great but it won’t match. Did I miss something?

Thanks.

Are you using the right intrinsic type? Does it have a chain or result?

How are you calling it from C? Are you declaring the intrinsic? This can fail if you mismatched the readnone or readonly to the actual intrinsic definition

Matt,

Here’s the DAG code:

Op is the SDValue incoming (the node I want to lower).

SDValue result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SDLoc(Op),
Op.getValueType(), DAG.getConstant(Intrinsic::my_intrinsic, SDLoc(Op),
Op.getValueType()), Op.getOperand(0));

The type of the intrinsic call is the same as the type of Op, hence I’m using Op.getValueType()

For the C code, I’m simply calling __builtin_myIntrinsic, where __builtin_myIntrinsic has been added to the appropriate files in clang and llvm and this maps down to the table gen just fine (we have lots of other intrinsics working the same way but we’ve never done it directly in DAG).

Matt,

  Here's the DAG code:

Op is the SDValue incoming (the node I want to lower).

SDValue result = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, SDLoc(Op),
      Op.getValueType(), DAG.getConstant(Intrinsic::my_intrinsic, SDLoc(Op),
      Op.getValueType()), Op.getOperand(0));

You got the wrong order. The chain is always the first operand. The intrinsic ID should be the second (and you should also be using getTargetConstant but I don’t think this really matters)

The type of the intrinsic call is the same as the type of Op, hence I'm using Op.getValueType()

For the C code, I'm simply calling __builtin_myIntrinsic, where __builtin_myIntrinsic has been added to the appropriate files in clang and llvm and this maps down to the table gen just fine (we have lots of other intrinsics working the same way but we've never done it directly in DAG).

If you’re using the builtin, it should be fine.

Matt,

The added intrinsic in DAG looks like:

0xbedb698: i32 = llvm.MyIntrinsic 0xbedb200, 0xbedac18 [ORD=4]

The builtin in DAG looks like:

0xbedb2a8: i32,ch = llvm 0xbedb158:1, 0xbedb200, 0xbedb158 [ORD=7] [ID=16]

The only difference I’m seeing is the extra operand, which is a ‘ch’ from a load.

given the following C code:

float b=16, a=0;
int main() {
float a = sqrt(b);
return0;
}

I’m trying to lower FSQRT down, but getting a casting issue, my code is:

SDValue XXXLowering::LowerFSQRT(SDValue Op, SelectionDAG &DAG) const {
SDLoc DL(Op);
EVT VT = Op.getValueType();
SDValue LHS = Op.getOperand(0);

SDValue newNode = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, DAG.getTargetConstantFP(Intrinsic::my_intrinsic, DL, VT), LHS);
return newNode;
}

The error I’m getting is: Assertion 'isa(Val) && “cast() argument of incompatible type!”

Is this the correct way to add intrinsic dag node?

Thanks.

The intrinsic ID is an int, not a float.

—escha

That’s what I thought but I got the same error with:

DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, VT, DAG.getTargetConstant(Intrinsic::my_intrinsic, DL, MVT::i16), LHS);

Thanks.

What should this call look like?

I’ve tried all the types (both for result and Intrinsic ID), can’t seem to find what cast is causing the issue here.

By looking at the SelectionDAGBuilder code, it seems that the type of the intrinsic code is the same as the pointer type. In your code it's MVT::i16, maybe you can try MVT::i32 or i64?

I'm looking at this, around line 4057:
DAG.getTargetConstant(Intrinsic, getCurSDLoc(),
                       TLI.getPointerTy(DAG.getDataLayout()))

This may not even be the place where the problem happens though. Do you have a full call trace from the crash?

-Krzysztof

When using DAG.getNode with INTRINSIC_WO_CHAIN, what should the first SDValue be? How do I get the chain here?

Thanks.

So I’m trying to lower ISD::FSQRT and in that lowering I’m trying to call an intrinsic (as the first node), the intrinsic has chain but the ISD::FSQRT does not. If I lower WO_CHAIN the intrinsic doesn’t match in table gen, when I try to lower W_CHAIN I can’t seem to get the Chain to put in the DAG.getNode call.

When I call this intrinsic outright in C code using “__builtin_XXX” the DAG shows a chain and it matches in table gen just fine. (I’ve included the intrinsic in all the appropriate .td and clang files, etc…).

Any suggestions?

Thank you.

DAG.getEntryNode() will give you the entry token (i.e. the chain that starts at the function entry).

-Krzysztof