https://github.com/Scheremo created https://github.com/llvm/llvm-project/pull/202564
First time adding ISA extension support in the frontend; please let me know if I made any mistakes or there is anything to improve. Clang did not expose builtins for the CORE-V XCVbitmanip extension, so C code could not directly use the existing backend support for cv.extract, cv.extractu, cv.insert, cv.bclr, cv.bset, cv.ff1, cv.fl1, cv.clb, cv.cnt, cv.ror, and cv.bitrev. [An overview of the ISA extension can be found here](https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/instruction_set_extensions.html#bit-manipulation-operations). Add the XCVbitmanip builtin definitions and lower them in Clang CodeGen. The operations that match generic LLVM bit operations are lowered to those forms: ff1 to cttz, cnt to ctpop, and ror to fshr. The remaining operations lower to llvm.riscv.cv.bitmanip intrinsics. Add a dedicated llvm.riscv.cv.bitmanip.fl1 intrinsic because cv.fl1 returns the index of the most significant set bit, not the leading-zero count returned by llvm.ctlz. Add Sema checking for: - requiring the xcvbitmanip extension for all XCVbitmanip builtins - cv.bitrev's constant immediate operands - cv.bitrev's valid immediate ranges CIR codegen now recognizes the new builtins and keeps them on the existing NYI path for unsupported RISC-V target builtins. Add coverage for: - LLVM IR lowering of all XCVbitmanip builtins - immediate and register operand forms for extract/extractu/insert/bclr/bset - generic intrinsic lowering for ff1/cnt/ror - dedicated target intrinsic lowering for fl1 - cv.bitrev immediate range diagnostics - cv.bitrev constant-operand diagnostics - missing-extension diagnostics for every XCVbitmanip builtin - LLVM CodeGen lowering of llvm.riscv.cv.bitmanip.fl1 to cv.fl1 Tested with: llvm-lit -sv \ clang/test/CodeGen/RISCV/riscv-xcvbitmanip.c \ clang/test/Sema/riscv-xcvbitmanip-builtins.c \ llvm/test/CodeGen/RISCV/xcvbitmanip.ll >From 3aef9f7f2a208155851b6152ad6bddd4855efbe5 Mon Sep 17 00:00:00 2001 From: Moritz Scherer <[email protected]> Date: Tue, 9 Jun 2026 10:13:07 +0200 Subject: [PATCH] [RISCV] Add Clang builtins for XCVbitmanip Clang did not expose builtins for the CORE-V XCVbitmanip extension, so C code could not directly use the existing backend support for cv.extract, cv.extractu, cv.insert, cv.bclr, cv.bset, cv.ff1, cv.fl1, cv.clb, cv.cnt, cv.ror, and cv.bitrev. [An overview of the ISA extension can be found here](https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/instruction_set_extensions.html#bit-manipulation-operations). Add the XCVbitmanip builtin definitions and lower them in Clang CodeGen. The operations that match generic LLVM bit operations are lowered to those forms: ff1 to cttz, cnt to ctpop, and ror to fshr. The remaining operations lower to llvm.riscv.cv.bitmanip intrinsics. Add a dedicated llvm.riscv.cv.bitmanip.fl1 intrinsic because cv.fl1 returns the index of the most significant set bit, not the leading-zero count returned by llvm.ctlz. Add Sema checking for: - requiring the xcvbitmanip extension for all XCVbitmanip builtins - cv.bitrev's constant immediate operands - cv.bitrev's valid immediate ranges CIR codegen now recognizes the new builtins and keeps them on the existing NYI path for unsupported RISC-V target builtins. Add coverage for: - LLVM IR lowering of all XCVbitmanip builtins - immediate and register operand forms for extract/extractu/insert/bclr/bset - generic intrinsic lowering for ff1/cnt/ror - dedicated target intrinsic lowering for fl1 - cv.bitrev immediate range diagnostics - cv.bitrev constant-operand diagnostics - missing-extension diagnostics for every XCVbitmanip builtin - LLVM CodeGen lowering of llvm.riscv.cv.bitmanip.fl1 to cv.fl1 Tested with: llvm-lit -sv \ clang/test/CodeGen/RISCV/riscv-xcvbitmanip.c \ clang/test/Sema/riscv-xcvbitmanip-builtins.c \ llvm/test/CodeGen/RISCV/xcvbitmanip.ll --- clang/include/clang/Basic/BuiltinsRISCVXCV.td | 15 +++ clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp | 12 +++ clang/lib/CodeGen/TargetBuiltins/RISCV.cpp | 51 +++++++++ clang/lib/Sema/SemaRISCV.cpp | 26 +++++ clang/test/CodeGen/RISCV/riscv-xcvbitmanip.c | 100 ++++++++++++++++++ clang/test/Sema/riscv-xcvbitmanip-builtins.c | 33 ++++++ llvm/include/llvm/IR/IntrinsicsRISCVXCV.td | 1 + llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td | 2 +- llvm/test/CodeGen/RISCV/xcvbitmanip.ll | 2 +- 9 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGen/RISCV/riscv-xcvbitmanip.c create mode 100644 clang/test/Sema/riscv-xcvbitmanip-builtins.c diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td index 65eb52b198775..763c48f363fb0 100644 --- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td +++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td @@ -18,6 +18,21 @@ class RISCVXCVBuiltin<string prototype, string features = ""> : TargetBuiltin { } let Attributes = [NoThrow, Const] in { +//===----------------------------------------------------------------------===// +// XCVbitmanip extension. +//===----------------------------------------------------------------------===// +def bitmanip_extract : RISCVXCVBuiltin<"int(unsigned int, unsigned short)", "xcvbitmanip">; +def bitmanip_extractu : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned short)", "xcvbitmanip">; +def bitmanip_insert : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned short, unsigned int)", "xcvbitmanip">; +def bitmanip_bclr : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned short)", "xcvbitmanip">; +def bitmanip_bset : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned short)", "xcvbitmanip">; +def bitmanip_ff1 : RISCVXCVBuiltin<"unsigned char(unsigned int)", "xcvbitmanip">; +def bitmanip_fl1 : RISCVXCVBuiltin<"unsigned char(unsigned int)", "xcvbitmanip">; +def bitmanip_clb : RISCVXCVBuiltin<"unsigned char(unsigned int)", "xcvbitmanip">; +def bitmanip_cnt : RISCVXCVBuiltin<"unsigned char(unsigned int)", "xcvbitmanip">; +def bitmanip_ror : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvbitmanip">; +def bitmanip_bitrev : RISCVXCVBuiltin<"unsigned int(unsigned int, _Constant unsigned char, _Constant unsigned char)", "xcvbitmanip">; + //===----------------------------------------------------------------------===// // XCValu extension. //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp index ec262922be942..9438a533672b1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinRISCV.cpp @@ -167,6 +167,18 @@ CIRGenFunction::emitRISCVBuiltinExpr(unsigned builtinID, const CallExpr *e) { break; } + // XCVbitmanip + case RISCV::BI__builtin_riscv_cv_bitmanip_extract: + case RISCV::BI__builtin_riscv_cv_bitmanip_extractu: + case RISCV::BI__builtin_riscv_cv_bitmanip_insert: + case RISCV::BI__builtin_riscv_cv_bitmanip_bclr: + case RISCV::BI__builtin_riscv_cv_bitmanip_bset: + case RISCV::BI__builtin_riscv_cv_bitmanip_ff1: + case RISCV::BI__builtin_riscv_cv_bitmanip_fl1: + case RISCV::BI__builtin_riscv_cv_bitmanip_clb: + case RISCV::BI__builtin_riscv_cv_bitmanip_cnt: + case RISCV::BI__builtin_riscv_cv_bitmanip_ror: + case RISCV::BI__builtin_riscv_cv_bitmanip_bitrev: // XCValu case RISCV::BI__builtin_riscv_cv_alu_addN: case RISCV::BI__builtin_riscv_cv_alu_addRN: diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp index 3bf7dd07d54d3..2215f45998175 100644 --- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp @@ -1304,6 +1304,57 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, return Builder.CreateCall(Fn, {}); } + // XCVbitmanip + case RISCV::BI__builtin_riscv_cv_bitmanip_extract: + Ops[1] = Builder.CreateIntCast(Ops[1], Int32Ty, /*isSigned*/ false); + ID = Intrinsic::riscv_cv_bitmanip_extract; + break; + case RISCV::BI__builtin_riscv_cv_bitmanip_extractu: + Ops[1] = Builder.CreateIntCast(Ops[1], Int32Ty, /*isSigned*/ false); + ID = Intrinsic::riscv_cv_bitmanip_extractu; + break; + case RISCV::BI__builtin_riscv_cv_bitmanip_insert: + Ops[1] = Builder.CreateIntCast(Ops[1], Int32Ty, /*isSigned*/ false); + ID = Intrinsic::riscv_cv_bitmanip_insert; + break; + case RISCV::BI__builtin_riscv_cv_bitmanip_bclr: + Ops[1] = Builder.CreateIntCast(Ops[1], Int32Ty, /*isSigned*/ false); + ID = Intrinsic::riscv_cv_bitmanip_bclr; + break; + case RISCV::BI__builtin_riscv_cv_bitmanip_bset: + Ops[1] = Builder.CreateIntCast(Ops[1], Int32Ty, /*isSigned*/ false); + ID = Intrinsic::riscv_cv_bitmanip_bset; + break; + case RISCV::BI__builtin_riscv_cv_bitmanip_ff1: { + Function *F = CGM.getIntrinsic(Intrinsic::cttz, Int32Ty); + Value *Result = Builder.CreateCall(F, {Ops[0], Builder.getInt1(false)}); + return Builder.CreateIntCast(Result, ResultType, /*isSigned*/ false); + } + case RISCV::BI__builtin_riscv_cv_bitmanip_fl1: { + Function *F = CGM.getIntrinsic(Intrinsic::riscv_cv_bitmanip_fl1); + Value *Result = Builder.CreateCall(F, {Ops[0]}); + return Builder.CreateIntCast(Result, ResultType, /*isSigned*/ false); + } + case RISCV::BI__builtin_riscv_cv_bitmanip_clb: { + Function *F = CGM.getIntrinsic(Intrinsic::riscv_cv_bitmanip_clb); + Value *Result = Builder.CreateCall(F, {Ops[0]}); + return Builder.CreateIntCast(Result, ResultType, /*isSigned*/ false); + } + case RISCV::BI__builtin_riscv_cv_bitmanip_cnt: { + Function *F = CGM.getIntrinsic(Intrinsic::ctpop, Int32Ty); + Value *Result = Builder.CreateCall(F, {Ops[0]}); + return Builder.CreateIntCast(Result, ResultType, /*isSigned*/ false); + } + case RISCV::BI__builtin_riscv_cv_bitmanip_ror: { + Function *F = CGM.getIntrinsic(Intrinsic::fshr, Int32Ty); + return Builder.CreateCall(F, {Ops[0], Ops[0], Ops[1]}); + } + case RISCV::BI__builtin_riscv_cv_bitmanip_bitrev: + Ops[1] = Builder.CreateIntCast(Ops[1], Int32Ty, /*isSigned*/ false); + Ops[2] = Builder.CreateIntCast(Ops[2], Int32Ty, /*isSigned*/ false); + ID = Intrinsic::riscv_cv_bitmanip_bitrev; + break; + // XCValu case RISCV::BI__builtin_riscv_cv_alu_addN: ID = Intrinsic::riscv_cv_alu_addN; diff --git a/clang/lib/Sema/SemaRISCV.cpp b/clang/lib/Sema/SemaRISCV.cpp index 56555b931b8d5..a256bd91b665c 100644 --- a/clang/lib/Sema/SemaRISCV.cpp +++ b/clang/lib/Sema/SemaRISCV.cpp @@ -588,11 +588,34 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI, << /* IsExtension */ true << TheCall->getSourceRange() << RF; } + auto CheckRequiredExtension = [&](StringRef RequiredExt) -> bool { + if (TI.hasFeature(RequiredExt) || FunctionFeatureMap.lookup(RequiredExt)) + return false; + return Diag(TheCall->getBeginLoc(), + diag::err_riscv_builtin_requires_extension) + << /* IsExtension */ true << TheCall->getSourceRange() + << RequiredExt; + }; + // vmulh.vv, vmulh.vx, vmulhu.vv, vmulhu.vx, vmulhsu.vv, vmulhsu.vx, // vsmul.vv, vsmul.vx are not included for EEW=64 in Zve64*. switch (BuiltinID) { default: break; + case RISCV::BI__builtin_riscv_cv_bitmanip_extract: + case RISCV::BI__builtin_riscv_cv_bitmanip_extractu: + case RISCV::BI__builtin_riscv_cv_bitmanip_insert: + case RISCV::BI__builtin_riscv_cv_bitmanip_bclr: + case RISCV::BI__builtin_riscv_cv_bitmanip_bset: + case RISCV::BI__builtin_riscv_cv_bitmanip_ff1: + case RISCV::BI__builtin_riscv_cv_bitmanip_fl1: + case RISCV::BI__builtin_riscv_cv_bitmanip_clb: + case RISCV::BI__builtin_riscv_cv_bitmanip_cnt: + case RISCV::BI__builtin_riscv_cv_bitmanip_ror: + case RISCV::BI__builtin_riscv_cv_bitmanip_bitrev: + if (CheckRequiredExtension("xcvbitmanip")) + return true; + break; case RISCVVector::BI__builtin_rvv_vmulhsu_vv: case RISCVVector::BI__builtin_rvv_vmulhsu_vx: case RISCVVector::BI__builtin_rvv_vmulhsu_vv_tu: @@ -688,6 +711,9 @@ bool SemaRISCV::CheckBuiltinFunctionCall(const TargetInfo &TI, case RISCVVector::BI__builtin_rvv_sf_vsettk: return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 3) || SemaRef.BuiltinConstantArgRange(TheCall, 2, 1, 3); + case RISCV::BI__builtin_riscv_cv_bitmanip_bitrev: + return SemaRef.BuiltinConstantArgRange(TheCall, 1, 0, 31) || + SemaRef.BuiltinConstantArgRange(TheCall, 2, 0, 3); case RISCVVector::BI__builtin_rvv_sf_mm_f_f_w1: case RISCVVector::BI__builtin_rvv_sf_mm_f_f_w2: case RISCVVector::BI__builtin_rvv_sf_mm_e5m2_e4m3_w4: diff --git a/clang/test/CodeGen/RISCV/riscv-xcvbitmanip.c b/clang/test/CodeGen/RISCV/riscv-xcvbitmanip.c new file mode 100644 index 0000000000000..efdafb708044b --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-xcvbitmanip.c @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvbitmanip -emit-llvm %s -o - \ +// RUN: -disable-O0-optnone | opt -S -passes=mem2reg | FileCheck %s + +#include <stdint.h> + +// CHECK-LABEL: @test_bitmanip_extract( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.extract(i32 {{.*}}, i32 31) +int32_t test_bitmanip_extract(uint32_t a) { + return __builtin_riscv_cv_bitmanip_extract(a, 31); +} + +// CHECK-LABEL: @test_bitmanip_extractr( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.extract(i32 {{.*}}, i32 {{.*}}) +int32_t test_bitmanip_extractr(uint32_t a, uint16_t b) { + return __builtin_riscv_cv_bitmanip_extract(a, b); +} + +// CHECK-LABEL: @test_bitmanip_extractu( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.extractu(i32 {{.*}}, i32 31) +uint32_t test_bitmanip_extractu(uint32_t a) { + return __builtin_riscv_cv_bitmanip_extractu(a, 31); +} + +// CHECK-LABEL: @test_bitmanip_extractur( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.extractu(i32 {{.*}}, i32 {{.*}}) +uint32_t test_bitmanip_extractur(uint32_t a, uint16_t b) { + return __builtin_riscv_cv_bitmanip_extractu(a, b); +} + +// CHECK-LABEL: @test_bitmanip_insert( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.insert(i32 {{.*}}, i32 31, i32 {{.*}}) +uint32_t test_bitmanip_insert(uint32_t a, uint32_t k) { + return __builtin_riscv_cv_bitmanip_insert(a, 31, k); +} + +// CHECK-LABEL: @test_bitmanip_insertr( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.insert(i32 {{.*}}, i32 {{.*}}, i32 {{.*}}) +uint32_t test_bitmanip_insertr(uint32_t a, uint16_t b, uint32_t k) { + return __builtin_riscv_cv_bitmanip_insert(a, b, k); +} + +// CHECK-LABEL: @test_bitmanip_bclr( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.bclr(i32 {{.*}}, i32 31) +uint32_t test_bitmanip_bclr(uint32_t a) { + return __builtin_riscv_cv_bitmanip_bclr(a, 31); +} + +// CHECK-LABEL: @test_bitmanip_bclrr( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.bclr(i32 {{.*}}, i32 {{.*}}) +uint32_t test_bitmanip_bclrr(uint32_t a, uint16_t b) { + return __builtin_riscv_cv_bitmanip_bclr(a, b); +} + +// CHECK-LABEL: @test_bitmanip_bset( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.bset(i32 {{.*}}, i32 31) +uint32_t test_bitmanip_bset(uint32_t a) { + return __builtin_riscv_cv_bitmanip_bset(a, 31); +} + +// CHECK-LABEL: @test_bitmanip_bsetr( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.bset(i32 {{.*}}, i32 {{.*}}) +uint32_t test_bitmanip_bsetr(uint32_t a, uint16_t b) { + return __builtin_riscv_cv_bitmanip_bset(a, b); +} + +// CHECK-LABEL: @test_bitmanip_ff1( +// CHECK: call i32 @llvm.cttz.i32(i32 {{.*}}, i1 false) +uint8_t test_bitmanip_ff1(uint32_t a) { + return __builtin_riscv_cv_bitmanip_ff1(a); +} + +// CHECK-LABEL: @test_bitmanip_fl1( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.fl1(i32 {{.*}}) +uint8_t test_bitmanip_fl1(uint32_t a) { + return __builtin_riscv_cv_bitmanip_fl1(a); +} + +// CHECK-LABEL: @test_bitmanip_clb( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.clb(i32 {{.*}}) +uint8_t test_bitmanip_clb(uint32_t a) { + return __builtin_riscv_cv_bitmanip_clb(a); +} + +// CHECK-LABEL: @test_bitmanip_cnt( +// CHECK: call i32 @llvm.ctpop.i32(i32 {{.*}}) +uint8_t test_bitmanip_cnt(uint32_t a) { + return __builtin_riscv_cv_bitmanip_cnt(a); +} + +// CHECK-LABEL: @test_bitmanip_ror( +// CHECK: call i32 @llvm.fshr.i32(i32 {{.*}}, i32 {{.*}}, i32 {{.*}}) +uint32_t test_bitmanip_ror(uint32_t a, uint32_t b) { + return __builtin_riscv_cv_bitmanip_ror(a, b); +} + +// CHECK-LABEL: @test_bitmanip_bitrev( +// CHECK: call i32 @llvm.riscv.cv.bitmanip.bitrev(i32 {{.*}}, i32 31, i32 3) +uint32_t test_bitmanip_bitrev(uint32_t a) { + return __builtin_riscv_cv_bitmanip_bitrev(a, 31, 3); +} diff --git a/clang/test/Sema/riscv-xcvbitmanip-builtins.c b/clang/test/Sema/riscv-xcvbitmanip-builtins.c new file mode 100644 index 0000000000000..12c6b1c05904b --- /dev/null +++ b/clang/test/Sema/riscv-xcvbitmanip-builtins.c @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvbitmanip -fsyntax-only -verify=xcv %s +// RUN: %clang_cc1 -triple riscv32 -DNO_XCVBITMANIP -fsyntax-only -verify=noxcv %s + +#include <stdint.h> + +#ifndef NO_XCVBITMANIP +void test_bitmanip_bitrev_range(uint32_t a) { + (void)__builtin_riscv_cv_bitmanip_bitrev(a, 31, 3); + (void)__builtin_riscv_cv_bitmanip_bitrev(a, -1, 0); // xcv-error {{argument value 255 is outside the valid range [0, 31]}} + (void)__builtin_riscv_cv_bitmanip_bitrev(a, 32, 0); // xcv-error {{argument value 32 is outside the valid range [0, 31]}} + (void)__builtin_riscv_cv_bitmanip_bitrev(a, 0, -1); // xcv-error {{argument value 255 is outside the valid range [0, 3]}} + (void)__builtin_riscv_cv_bitmanip_bitrev(a, 0, 4); // xcv-error {{argument value 4 is outside the valid range [0, 3]}} +} + +void test_bitmanip_bitrev_constant(uint32_t a, uint8_t b) { + (void)__builtin_riscv_cv_bitmanip_bitrev(a, b, 0); // xcv-error {{argument to '__builtin_riscv_cv_bitmanip_bitrev' must be a constant integer}} + (void)__builtin_riscv_cv_bitmanip_bitrev(a, 0, b); // xcv-error {{argument to '__builtin_riscv_cv_bitmanip_bitrev' must be a constant integer}} +} +#else +void test_bitmanip_requires_xcvbitmanip(uint32_t a, uint16_t b, uint32_t k) { + (void)__builtin_riscv_cv_bitmanip_extract(a, b); // noxcv-error {{builtin requires at least one of the following extensions: xcvbitmanip}} + (void)__builtin_riscv_cv_bitmanip_extractu(a, b); // noxcv-error {{builtin requires at least one of the following extensions: xcvbitmanip}} + (void)__builtin_riscv_cv_bitmanip_insert(a, b, k); // noxcv-error {{builtin requires at least one of the following extensions: xcvbitmanip}} + (void)__builtin_riscv_cv_bitmanip_bclr(a, b); // noxcv-error {{builtin requires at least one of the following extensions: xcvbitmanip}} + (void)__builtin_riscv_cv_bitmanip_bset(a, b); // noxcv-error {{builtin requires at least one of the following extensions: xcvbitmanip}} + (void)__builtin_riscv_cv_bitmanip_ff1(a); // noxcv-error {{builtin requires at least one of the following extensions: xcvbitmanip}} + (void)__builtin_riscv_cv_bitmanip_fl1(a); // noxcv-error {{builtin requires at least one of the following extensions: xcvbitmanip}} + (void)__builtin_riscv_cv_bitmanip_clb(a); // noxcv-error {{builtin requires at least one of the following extensions: xcvbitmanip}} + (void)__builtin_riscv_cv_bitmanip_cnt(a); // noxcv-error {{builtin requires at least one of the following extensions: xcvbitmanip}} + (void)__builtin_riscv_cv_bitmanip_ror(a, k); // noxcv-error {{builtin requires at least one of the following extensions: xcvbitmanip}} + (void)__builtin_riscv_cv_bitmanip_bitrev(a, 31, 3); // noxcv-error {{builtin requires at least one of the following extensions: xcvbitmanip}} +} +#endif diff --git a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td index 465665c838bae..ae3eb3b2d3dee 100644 --- a/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCVXCV.td @@ -53,6 +53,7 @@ let TargetPrefix = "riscv" in { [IntrNoMem, IntrSpeculatable]>; def int_riscv_cv_bitmanip_clb : ScalarCoreVBitManipGprIntrinsic; + def int_riscv_cv_bitmanip_fl1 : ScalarCoreVBitManipGprIntrinsic; def int_riscv_cv_bitmanip_bitrev : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td index 8b52fc965e601..5cb4c7ba84ea8 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td @@ -734,7 +734,7 @@ let Predicates = [HasVendorXCVbitmanip, IsRV32] in { (CV_LO5 cv_uimm10:$imm))>; def : PatGpr<cttz, CV_FF1, i32>; - def : PatGpr<ctlz, CV_FL1, i32>; + def : PatGpr<int_riscv_cv_bitmanip_fl1, CV_FL1>; def : PatGpr<int_riscv_cv_bitmanip_clb, CV_CLB>; def : PatGpr<ctpop, CV_CNT, i32>; diff --git a/llvm/test/CodeGen/RISCV/xcvbitmanip.ll b/llvm/test/CodeGen/RISCV/xcvbitmanip.ll index 7e63efac9b62f..cb40bbc10fb9a 100644 --- a/llvm/test/CodeGen/RISCV/xcvbitmanip.ll +++ b/llvm/test/CodeGen/RISCV/xcvbitmanip.ll @@ -117,7 +117,7 @@ define i32 @test.cv.fl1(i32 %a) { ; CHECK: # %bb.0: ; CHECK-NEXT: cv.fl1 a0, a0 ; CHECK-NEXT: ret - %1 = call i32 @llvm.ctlz.i32(i32 %a, i1 0) + %1 = call i32 @llvm.riscv.cv.bitmanip.fl1(i32 %a) ret i32 %1 } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
