Question about adding a RISCV intrinsic

Hi,

I have one question regarding adding a custom RISCV instruction’s intrinsic. The total process is just for a preparation of my further work, so I raise such kind of topic while searching the related answers in this website simultaneously: as I have not read this website very carefully until now (I am working on it, and, my apology if it is just a kind of simple and stupid question), it would be greatly kind of you if any related links could be provided!

PS: I would like to set an intrinsic function for my existing custom instruction, so I could use it in my c file instead of writing asm.

I have set a kind of 64 bit RISCV instruction consisting of two VCIX instructions. The whole settings are shown below:

RISCVInstrFormats.td

class RVInst64<dag outs, dag ins, string opcodestr, string argstr,
             list<dag> pattern, InstFormat format>
    : RVInstCommon<outs, ins, opcodestr, argstr, pattern, format> {
    field bits<64> Inst;
    // SoftFail is a field the disassembler can use to provide a way for
    // instructions to not match without killing the whole decode process. It is
    // mainly used for ARM, but Tablegen expects this field to exist or it fails
    // to build the decode table.
    field bits<64> SoftFail = 0;
    let Size = 8;
}

RISCVInstrInfo.td

let DecoderNamespace = "xxx" in {
  class XsgMix_VC_X_VC_I<dag outs, string opcodestr, dag ins, string argstr>
    : RVInst64<outs, ins, opcodestr, argstr, [], InstFormatPseudo> {
    bits<4> ms2;
    bits<4> ms1;
    bits<4> md;
    bits<5> rs;
    let Inst{63-60} = 0b0000;
    let Inst{59-58} = 0b00;
    let Inst{57} = 0b1;
    let Inst{56-52} = 0b00000;
    let Inst{51-47} = rs;
    let Inst{46-39} = 0b10000000;
    let Inst{38-32} = 0b1011011;
    let Inst{31-28} = 0b0000;
    let Inst{27-26} = 0b10;
    let Inst{25} = 0b1;
    let Inst{24} = 0b1;
    let Inst{23-20} = ms2;
    let Inst{19} = 0b0;
    let Inst{18-15} = ms1;
    let Inst{14-12} = 0b011;
    let Inst{11} = 0b0;
    let Inst{10-7} = md;
    let Inst{6-0} = 0b1011011;
  }
}

let Predicates = [HasVendorxxx] in {
  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in {
      def XsgmBit64:      XsgMix_VC_X_VC_I<(outs MRF:$md), "sg.bit64test", (ins GPR:$rs, MRF:$ms1, MRF:$ms2), "$md,$rs,$ms1,$ms2">;
    }

MRF itself is a kind of uimm4-like type.
Meanwhile I have already set the corresponding AsmParser, Disassembler and Printer. This instruction has already passed my llvm-clang, llvm-mc along with llvm-objdump check, everything is perfect.

Now I would like to add an intrinsic function for this instruction. I set the corresponding object in IntrinsicsXXX.td:

let TargetPrefix = "riscv" in {
  def int_riscv_sg_bit64test : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
}

After that I come back to RISCVInstrInfo.td and do such kind of operations:

def xsg_uimm4 : TImmLeaf<XLenVT, [{return isUInt<4>(Imm);}]>;
class PatCoreTest <string intr, string asm>
  : Pat<(!cast<Intrinsic>("int_riscv_sg_" # intr) GPR:$rs, xsg_uimm4:$ms1, xsg_uimm4:$ms2),
        (!cast<XsgMix_VC_X_VC_I>("Xsgm" # asm) GPR:$rs, xsg_uimm4:$ms1, xsg_uimm4:$ms2)>;

def : PatCoreTest<"bit64test", "Bit64">;

(It seems that the Pat class does not accept any self-defined class like MRF I have already mentioned before, so I use TImmLeaf instead [hope it does not make any problem])
However it does not work. I am still quite confused about how to use it with clang, and my IR test fails with a serious bug:


declare i32 @llvm.riscv.sg.bit64test(i32, i32, i32)

define i32 @test.mac(i32 %a, i32 %b, i32 %c) {
; CHECK-LABEL: test.mac:
; CHECK:       # %bb.0:
; CHECK-NEXT:    cv.mac a2, a0, a1
; CHECK-NEXT:    mv a0, a2
; CHECK-NEXT:    ret
  %1 = call i32 @llvm.riscv.sg.bit64test(i32 %a, i32 %b, i32 %c)
  ret i32 %1
}

There is a bug while I tried to use llc:

LLVM ERROR: Cannot select: 0x634023c00d10: i64 = RISCVISD::BREV8 0x634023c00e60
  0x634023c00e60: i64,ch = CopyFromReg 0x634023b8d240, Register:i64 %1
    0x634023c00df0: i64 = Register %1
In function: test.mac
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: /opt/LLVM/install/bin/llc -mtriple=riscv64 -mattr=+m -mattr=xsgmat -verify-machineinstrs xsgmat.ll
1.      Running pass 'Function Pass Manager' on module 'xsgmat.ll'.
2.      Running pass 'RISC-V DAG->DAG Pattern Instruction Selection' on function '@test.mac'
 #0 0x00006340209ac010 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/LLVM/install/bin/llc+0x1595010)
 #1 0x00006340209a95de SignalHandler(int) Signals.cpp:0:0
 #2 0x00007afe8b442520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #3 0x00007afe8b4969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #4 0x00007afe8b4969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #5 0x00007afe8b4969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #6 0x00007afe8b442476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #7 0x00007afe8b4287f3 abort ./stdlib/abort.c:81:7
 #8 0x000063401f73d810 llvm::RISCVISAInfo::updateImplication() (.cold) RISCVISAInfo.cpp:0:0
 #9 0x000063402075f6f8 llvm::SelectionDAGISel::CannotYetSelect(llvm::SDNode*) (/opt/LLVM/install/bin/llc+0x13486f8)
#10 0x0000634020763012 llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) (/opt/LLVM/install/bin/llc+0x134c012)
#11 0x000063401f87a9ff llvm::RISCVDAGToDAGISel::Select(llvm::SDNode*) crtstuff.c:0:0
#12 0x000063402075c746 llvm::SelectionDAGISel::DoInstructionSelection() (/opt/LLVM/install/bin/llc+0x1345746)
#13 0x0000634020767a69 llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/opt/LLVM/install/bin/llc+0x1350a69)
#14 0x000063402076a6dc llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/opt/LLVM/install/bin/llc+0x13536dc)
#15 0x000063402076cabe llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (.part.0) SelectionDAGISel.cpp:0:0
#16 0x000063401fd81890 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (.part.0) MachineFunctionPass.cpp:0:0
#17 0x000063402029132a llvm::FPPassManager::runOnFunction(llvm::Function&) (/opt/LLVM/install/bin/llc+0xe7a32a)
#18 0x00006340202914b4 llvm::FPPassManager::runOnModule(llvm::Module&) (/opt/LLVM/install/bin/llc+0xe7a4b4)
#19 0x0000634020291ef4 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/opt/LLVM/install/bin/llc+0xe7aef4)
#20 0x000063401f749513 main (/opt/LLVM/install/bin/llc+0x332513)
#21 0x00007afe8b429d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#22 0x00007afe8b429e40 call_init ./csu/../csu/libc-start.c:128:20
#23 0x00007afe8b429e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#24 0x000063401f7b0665 _start (/opt/LLVM/install/bin/llc+0x399665)

I think currently I have no idea which process to follow, but I am trying to figure it out by searching on the Internet. However any current assistance would be greatly appreciated!!! (I will check Github commits as well).