Hi, folks,
I’m struggling to add a new intrinsic to the RISCV target. Following the instructions here, I’ve tried to add the definition of my intrinsic to IntrinsicsRISCV.td
and the implementation to RISCVISelLowering.cpp
(details below). The compiler builds but when I try to use it to compile my code I get a segmentation fault (details below) in SelectionDAG::getNode
here.
I think the root cause might be that my implementation in RISCVISelLowering does not match my declaration in IntrinsicsRISCV.td, but I’m not sure. Can anybody give me any pointers?
Thanks,
-Russ
IntrinsicsRISCV.td:
let TargetPrefix = "riscv" in {
def int_riscv_my_custom_intrinsic : DefaultAttrsIntrinsic<[], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<1>>]>;
}
RISCVISelLowering.cpp:
// in RISCVTargetLowering::LowerINTRINSIC_VOID
case Intrinsic::riscv_my_custom_intrinsic {
SDLoc DL(Op);
SDValue firstArg= Op.getOperand(1);
SDValue secondArg = Op.getOperand(2);
// Clear out everything but the bottom 2 bits of secondArg
SDValue secondArgLowBits = DAG.getNode(ISD::AND, DL, MVT::i32, secondArg,
DAG.getConstant(0x3, DL, MVT::i32));
// Shift secondArgLowBits over to make room for firstArg
SDValue shiftedSecondArg =
DAG.getNode(ISD::SHL, DL, MVT::i32, secondArgLowBits ,
DAG.getConstant(30, DL, MVT::i32));
// Clear out the top 2 bits of firstArg
SDValue firstArgLowBits =
DAG.getNode(ISD::AND, DL, MVT::i32, firstArg,
DAG.getConstant(0x3FFFFFFF, DL, MVT::i32));
// OR the arguments together into a single argument for the CFS call.
SDValue CfsArg =
DAG.getNode(ISD::OR, DL, MVT::i32, shiftedSecondArg , firstArgLowBits);
// Copy the combined argument to X12
SDValue LI = DAG.getNode(ISD::CopyToReg, DL, MVT::Other,
{DAG.getRegister(RISCV::X12, MVT::i32), CfsArg});
// All CFS instructions are offset from a fixed address stored in X13
// (0xFFFFFE00)
SDValue BaseAddr = DAG.getRegister(RISCV::X13, MVT::i32);
SDValue CFSAddrWithOffset = DAG.getNode(ISD::ADD, DL, MVT::i32, BaseAddr,
DAG.getConstant(2, DL, MVT::i32));
// Store the value in X12 to CFSAddrWithOffset.
return DAG.getNode(
ISD::STORE, DL, MVT::Other,
{LI, DAG.getRegister(RISCV::X12, MVT::i32), CFSAddrWithOffset});
}
Sample .ll
target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
target triple = "riscv32"
define void @main() {
; call the new intrinsic
call void @llvm.riscv.my_custom_intrinsic(i32 500, i32 1)
ret void
}
declare void @llvm.riscv.my_custom_intrinsic(i32, i32)
Segmentation Fault
Stack dump:
0. Program arguments: ./install/bin/llc -march=riscv32 -filetype=asm -O3 test_custom_intrinsic.ll -o test_custom_intrinsic.S
1. Running pass 'Function Pass Manager' on module 'test_custom_intrinsic.ll'.
2. Running pass 'RISC-V DAG->DAG Pattern Instruction Selection' on function '@main'
#0 0x000055cf5f25b960 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (./install/bin/llc+0x2ee9960)
#1 0x000055cf5f259264 SignalHandler(int) Signals.cpp:0:0
#2 0x00007f03c8bdc520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
#3 0x000055cf5f01d2b1 llvm::SelectionDAG::getNode(unsigned int, llvm::SDLoc const&, llvm::SDVTList, llvm::ArrayRef<llvm::SDValue>, llvm::SDNodeFlags) (./install/bin/llc+0x2cab2b1)
#4 0x000055cf5efac68f llvm::SelectionDAGBuilder::visitTargetIntrinsic(llvm::CallInst const&, unsigned int) (./install/bin/llc+0x2c3a68f)
#5 0x000055cf5ef8b064 llvm::SelectionDAGBuilder::visitIntrinsicCall(llvm::CallInst const&, unsigned int) (./install/bin/llc+0x2c19064)
#6 0x000055cf5efccce0 llvm::SelectionDAGBuilder::visit(llvm::Instruction const&) (./install/bin/llc+0x2c5ace0)
#7 0x000055cf5f040056 llvm::SelectionDAGISel::SelectBasicBlock(llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void>, false, true>, llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, false, false, void>, false, true>, bool&) (./install/bin/llc+0x2cce056)
#8 0x000055cf5f04155c llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (./install/bin/llc+0x2ccf55c)
#9 0x000055cf5f04385e llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (.part.0) SelectionDAGISel.cpp:0:0
#10 0x000055cf5e614bb4 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) MachineFunctionPass.cpp:0:0
#11 0x000055cf5eb0c15a llvm::FPPassManager::runOnFunction(llvm::Function&) (./install/bin/llc+0x279a15a)
#12 0x000055cf5eb0c2e4 llvm::FPPassManager::runOnModule(llvm::Module&) (./install/bin/llc+0x279a2e4)
#13 0x000055cf5eb0cce4 llvm::legacy::PassManagerImpl::run(llvm::Module&) (./install/bin/llc+0x279ace4)
#14 0x000055cf5c98394b compileModule(char**, llvm::LLVMContext&) llc.cpp:0:0
#15 0x000055cf5c8c0086 main (./install/bin/llc+0x54e086)
#16 0x00007f03c8bc3d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#17 0x00007f03c8bc3e40 call_init ./csu/../csu/libc-start.c:128:20
#18 0x00007f03c8bc3e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#19 0x000055cf5c97b235 _start (./install/bin/llc+0x609235)
Segmentation fault (core dumped)