Selection pattern for Intrinsic functions

I am a beginner LLVM Backend Developer for RISCV. I was writing selection patterns for several bit manipulation instructions. I understood that I should use intrinsic functions instead of writing selection DAG in this post. I used intrinsic functions for both selection pattern and c code. However, I couldn’t convert the ctpop, and ctlz instructions to target instructions.
I also tried to look for similar questions and got help from them. Here is the most related one.
My selection patterns and c codes are below.

//pattern for cntp
def : Pat< (ctpop GPR:$src1), (cntp GPR:$src1) >;//pcnt -> cpop name changed
// I also tried this but not working. // def : Pat< (i32 (ctpop i32:$src1)), (cntp i32:$src1) >;
//pattern for cntz
def : Pat< (ctlz GPR:$src1), (cntz GPR:$src1) >;

unsigned int clz2(unsigned int rs1){
    return __builtin_clz(rs1);

unsigned int cntp_fun(unsigned int rs1){
    return __builtin_popcount(rs1);

I can see the intrinsic functions in ll files. However, I couldn’t see the cntz and cntp which are custom instructions in assembly files. I only saw many basic instructions to make the same process.

In the future, I will aim to use ctpop and ctlz in different selection patterns, not one-to-one as in this case.

I think it’s because you need to add lines in RISCVISelLowering.cpp declaring that you have patterns to support these intrinsics. Otherwise generic lowering code will re-expand them into convoluted arithmetic.

Something like setOperationAction(ISD::CTPOP, MVT::i32, Legal) in amongst all the other setOperationActions in that file. And make sure it’s not overridden by a second call to that function later, because it looks like RISC-V explicitly sets them to Expand in at least some cases.

1 Like

Thank you so much.
I wrote the setOperationAction(ISD::CTPOP, MVT::i32, Legal); instead of setOperationAction(ISD::CTPOP, XLenVT, Expand); under an if if (Subtarget.hasStdExtZbb()) {. It solved my problem.

There was one more line setOperationAction(ISD::CTPOP, XLenVT, Expand); in the for loopfor (MVT VT : IntVecVTs) { as you said. Changing that line too doesn’t affect the result. Could you explain what is it for and when (or will) I need to change it?

The one in the for loop is for handling the SIMD vector case. You can probably ignore it for now.

1 Like