[cfe-dev] Questions on adding a CLANG builtin to connect to a LLVM intrinsic

David Mallasén Quintana via cfe-dev cfe-dev at lists.llvm.org
Wed Jan 26 09:00:46 PST 2022


Thank you for your answers Jess and Craig.
Now the Clang builtin seems to be working and, as Craig predicted, I
got a new error "fatal error: error in backend: Cannot select:
intrinsic %llvm.riscv.foo" that I will try to debug with your
comments.

Best regards,
David

El mié, 26 ene 2022 a las 17:28, Craig Topper
(<craig.topper at gmail.com>) escribió:
>
> I see another issue that you’ll hit later. Your intrinsic doesn’t have IntrNoMem and has no results. So it will be in SelectionDAG as INTRINSIC_VOID rather that INTRINSIC_WO_CHAIN. Your getNode call will need to copy the chain input and output. And riscv_foo needs the SDNPHasChain property.
>
> On Wed, Jan 26, 2022 at 5:58 AM Jessica Clarke via cfe-dev <cfe-dev at lists.llvm.org> wrote:
>>
>> On 26 Jan 2022, at 12:19, David Mallasén Quintana via cfe-dev <cfe-dev at lists.llvm.org> wrote:
>> >
>> > Hello,
>> >
>> > Following up on this, and trying to do something similar to
>> > https://github.com/llvm/llvm-project/commit/16877c5, I am trying to
>> > add a simple Clang builtin: void __builtin_riscv_foo() that should
>> > output an intrinsic @llvm.riscv.foo() which will outpu, with a pattern
>> > in the backend, a simple custom instruction FOO without parameters.
>> > However, when compiling I receive the following error:
>> >
>> > clang: llvm/lib/IR/Function.cpp:844: std::string
>> > llvm::Intrinsic::getName(llvm::Intrinsic::ID,
>> > llvm::ArrayRef<llvm::Type*>, llvm::Module*, llvm::FunctionType*):
>> > Assertion `(Tys.empty() || Intrinsic::isOverloaded(Id)) && "This
>> > version of getName is for overloaded intrinsics only"' failed.
>>
>> As you can see, it’s telling you that you’re treating your intrinsic as
>> an overloaded intrinsic, but your intrinsic isn’t polymorphic (it
>> doesn’t even have any arguments or return types, let alone overloaded).
>> You can see towards the bottom of EmitRISCVBuiltinExpr the
>> IntrinsicTypes = {ResultType}, which is the list of types used to
>> instantiate the overloads. Since you have no overloads, that list
>> should be empty for your intrinsic, so you should not be reusing that
>> bit of code and instead have a separate top-level case statement.
>>
>> Jess
>>
>> > PLEASE submit a bug report to https://bugs.llvm.org/ and include the
>> > crash backtrace, preprocessed source, and associated run script.
>> > Stack dump:
>> > 0.    Program arguments: clang --target=riscv64 -march=rv64gcxbar
>> > intrinsics_test.c -c -o intrinsics_test.o
>> > 1.    <eof> parser at end of file
>> > 2.    intrinsics_test.c:21:6: LLVM IR generation of declaration 'test'
>> > 3.    intrinsics_test.c:21:6: Generating code for declaration 'test'
>> > 4.    intrinsics_test.c:22:33: LLVM IR generation of compound statement ('{}')
>> > 5.    intrinsics_test.c:23:37: LLVM IR generation of compound statement ('{}')
>> >
>> > To get to this point I have added the following code:
>> > In clang/include/clang/Basic/BuiltinsRISCV.def:
>> >    TARGET_BUILTIN(__builtin_riscv_foo, "v", "n", "xbar")
>> >
>> > In clang/lib/CodeGen/CGBuiltin.cpp : EmitRISCVBuiltinExpr:
>> >    case RISCV::BI__builtin_riscv_foo: {
>> > and later in that same function
>> >    case RISCV::BI__builtin_riscv_foo:
>> >        ID = Intrinsic::riscv_foo;
>> >        break;
>> >
>> > In llvm/include/llvm/IR/IntrinsicsRISCV.td:
>> >    let TargetPrefix = "riscv" in {
>> >        def int_riscv_foo : Intrinsic<[], [], []>;
>> >    }
>> >
>> > In llvm/lib/Target/RISCV/RISCVISelLowering.h:
>> >    FOO, // Before ISD::FIRST_TARGET_MEMORY_OPCODE
>> >
>> > In llvm/lib/Target/RISCV/RISCVISelLowering.cpp : LowerINTRINSIC_WO_CHAIN:
>> >    case Intrinsic::riscv_foo: {
>> >        return DAG.getNode(RISCVISD::FOO, DL, XLenVT);
>> >    }
>> > and in RISCVTargetLowering::getTargetNodeName:
>> >   NODE_NAME_CASE(FOO)
>> >
>> > In llvm/lib/Target/RISCV/RISCVInstrInfoBar.td
>> >    def riscv_foo : SDNode<"RISCVISD::FOO", SDTypeProfile<0, 0, []>>;
>> >    def : Pat<(riscv_foo), (FOO)>;
>> >
>> > I think the test for the Clang builtin should be:
>> > // RUN: %clang_cc1 -triple riscv64 -target-feature +xbar -emit-llvm %s -o - \
>> > // RUN:     | FileCheck %s  -check-prefix=RV64Xbar
>> >
>> > // RV64Xbar-LABEL: @foo(
>> > // RV64Xbar-NEXT:  entry:
>> > // RV64Xbar-NEXT:    call void @llvm.riscv.foo()
>> > // RV64Xbar-NEXT:    ret void
>> > //
>> > void foo() {
>> >    __builtin_riscv_foo();
>> > }
>> >
>> > Is there something missing that I can't find? I have tried small
>> > variations of this code with no success.
>> >
>> > Best regards,
>> > David
>> >
>> > El mar, 18 ene 2022 a las 12:34, David Mallasén Quintana
>> > (<dmallase at ucm.es>) escribió:
>> >>
>> >> Hello,
>> >>
>> >> I have added new instructions to the RISC-V LLVM backend for some
>> >> specific hardware I developed and I want to access a sequence of them
>> >> directly from C code. As of now I do this using inline assembly but it
>> >> can be a bit cumbersome. If I'm not mistaken the way to go would be to
>> >> access this functionality from C with CLANG builtins and lowering this
>> >> to machine code with LLVM intrinsics that generate my target RISC-V
>> >> instructions.
>> >>
>> >> I have seen the documentation on how to add LLVM intrinsics. However,
>> >> I can't find something similar with CLANG builtins, so any pointers to
>> >> some documentation would be greatly appreciated. Also, if there is a
>> >> better way of achieving this I would be grateful for some information
>> >> on how it could be done.
>> >>
>> >> Best regards,
>> >> David
>> > _______________________________________________
>> > cfe-dev mailing list
>> > cfe-dev at lists.llvm.org
>> > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
> --
> ~Craig


More information about the cfe-dev mailing list