diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td index 4cc89a8a9d8af..7cdc274492004 100644 --- a/clang/include/clang/Basic/BuiltinsRISCV.td +++ b/clang/include/clang/Basic/BuiltinsRISCV.td @@ -137,6 +137,19 @@ def sm3p0 : RISCVBuiltin<"unsigned int(unsigned int)">; def sm3p1 : RISCVBuiltin<"unsigned int(unsigned int)">; } // Features = "zksh" +//===----------------------------------------------------------------------===// +// Zimop extension. +//===----------------------------------------------------------------------===// +let Features = "experimental-zimop" in { +def mopr_32 : RISCVBuiltin<"unsigned int(unsigned int, _Constant unsigned int)">; +def moprr_32 : RISCVBuiltin<"unsigned int(unsigned int, unsigned int, _Constant unsigned int)">; +} // Features = "experimental-zimop" + +let Features = "experimental-zimop,64bit" in { +def mopr_64 : RISCVBuiltin<"uint64_t(uint64_t, _Constant uint64_t)">; +def moprr_64 : RISCVBuiltin<"uint64_t(uint64_t, uint64_t, _Constant uint64_t)">; +} // Features = "experimental-zimop,64bit" + } // Attributes = [Const, NoThrow] //===----------------------------------------------------------------------===// diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index cc30665a4eeee..350c231fcb8b8 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -21481,6 +21481,19 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, ID = Intrinsic::riscv_sm3p1; break; + // Zimop + case RISCV::BI__builtin_riscv_mopr_32: + case RISCV::BI__builtin_riscv_mopr_64: + ID = Intrinsic::riscv_mopr; + IntrinsicTypes = {ResultType}; + break; + + case RISCV::BI__builtin_riscv_moprr_32: + case RISCV::BI__builtin_riscv_moprr_64: + ID = Intrinsic::riscv_moprr; + IntrinsicTypes = {ResultType}; + break; + // Zihintntl case RISCV::BI__builtin_riscv_ntl_load: { llvm::Type *ResTy = ConvertType(E->getType()); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 561764edd0810..919f632c0f19f 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5746,6 +5746,14 @@ bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI, // Check if rnum is in [0, 10] case RISCV::BI__builtin_riscv_aes64ks1i: return SemaBuiltinConstantArgRange(TheCall, 1, 0, 10); + // Check if n of mop.r.[n] is in [0, 31] + case RISCV::BI__builtin_riscv_mopr_32: + case RISCV::BI__builtin_riscv_mopr_64: + return SemaBuiltinConstantArgRange(TheCall, 1, 0, 31); + // Check if n of mop.rr.[n] is in [0, 7] + case RISCV::BI__builtin_riscv_moprr_32: + case RISCV::BI__builtin_riscv_moprr_64: + return SemaBuiltinConstantArgRange(TheCall, 2, 0, 7); // Check if value range for vxrm is in [0, 3] case RISCVVector::BI__builtin_rvv_vaaddu_vv: case RISCVVector::BI__builtin_rvv_vaaddu_vx: diff --git a/clang/test/CodeGen/RISCV/rvb-intrinsics/zimop-invalid.c b/clang/test/CodeGen/RISCV/rvb-intrinsics/zimop-invalid.c new file mode 100644 index 0000000000000..7459c7114574d --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvb-intrinsics/zimop-invalid.c @@ -0,0 +1,28 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple riscv32 -target-feature +experimental-zimop -emit-llvm -verify %s -o - \ +// RUN: -disable-O0-optnone +// RUN: %clang_cc1 -triple riscv64 -target-feature +experimental-zimop -emit-llvm -verify %s -o - \ +// RUN: -disable-O0-optnone + +#include + +#if __riscv_xlen == 64 + +uint64_t mopr_41_64(uint64_t a) { + return __builtin_riscv_mopr_64(a, 41); // expected-error {{argument value 41 is outside the valid range [0, 31]}} +} + +uint64_t moprr_8_64(uint64_t a, uint64_t b) { + return __builtin_riscv_moprr_64(a, b, 8); // expected-error {{argument value 8 is outside the valid range [0, 7]}} +} + +#endif + +uint32_t mopr_88_32(uint32_t a) { + return __builtin_riscv_mopr_32(a, 88); // expected-error {{argument value 88 is outside the valid range [0, 31]}} +} + +uint32_t moprr_16_32(uint32_t a, uint32_t b) { + return __builtin_riscv_moprr_32(a, b, 16); // expected-error {{argument value 16 is outside the valid range [0, 7]}} +} + diff --git a/clang/test/CodeGen/RISCV/rvb-intrinsics/zimop.c b/clang/test/CodeGen/RISCV/rvb-intrinsics/zimop.c new file mode 100644 index 0000000000000..b4367e33bdc19 --- /dev/null +++ b/clang/test/CodeGen/RISCV/rvb-intrinsics/zimop.c @@ -0,0 +1,105 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple riscv32 -target-feature +experimental-zimop -emit-llvm %s -o - \ +// RUN: -disable-O0-optnone | opt -S -passes=mem2reg \ +// RUN: | FileCheck %s -check-prefix=RV32ZIMOP +// RUN: %clang_cc1 -triple riscv64 -target-feature +experimental-zimop -emit-llvm %s -o - \ +// RUN: -disable-O0-optnone | opt -S -passes=mem2reg \ +// RUN: | FileCheck %s -check-prefix=RV64ZIMOP + +#include + +#if __riscv_xlen == 64 +// RV64ZIMOP-LABEL: @mopr_0_64( +// RV64ZIMOP-NEXT: entry: +// RV64ZIMOP-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.mopr.i64(i64 [[A:%.*]], i64 0) +// RV64ZIMOP-NEXT: ret i64 [[TMP0]] +// +uint64_t mopr_0_64(uint64_t a) { + return __builtin_riscv_mopr_64(a, 0); +} + +// RV64ZIMOP-LABEL: @mopr_31_64( +// RV64ZIMOP-NEXT: entry: +// RV64ZIMOP-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.mopr.i64(i64 [[A:%.*]], i64 31) +// RV64ZIMOP-NEXT: ret i64 [[TMP0]] +// +uint64_t mopr_31_64(uint64_t a) { + return __builtin_riscv_mopr_64(a, 31); +} + +// RV64ZIMOP-LABEL: @moprr_0_64( +// RV64ZIMOP-NEXT: entry: +// RV64ZIMOP-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.moprr.i64(i64 [[A:%.*]], i64 [[B:%.*]], i64 0) +// RV64ZIMOP-NEXT: ret i64 [[TMP0]] +// +uint64_t moprr_0_64(uint64_t a, uint64_t b) { + return __builtin_riscv_moprr_64(a, b, 0); +} + +// RV64ZIMOP-LABEL: @moprr_7_64( +// RV64ZIMOP-NEXT: entry: +// RV64ZIMOP-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.moprr.i64(i64 [[A:%.*]], i64 [[B:%.*]], i64 7) +// RV64ZIMOP-NEXT: ret i64 [[TMP0]] +// +uint64_t moprr_7_64(uint64_t a, uint64_t b) { + return __builtin_riscv_moprr_64(a, b, 7); +} + +#endif + +// RV32ZIMOP-LABEL: @mopr_0_32( +// RV32ZIMOP-NEXT: entry: +// RV32ZIMOP-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mopr.i32(i32 [[A:%.*]], i32 0) +// RV32ZIMOP-NEXT: ret i32 [[TMP0]] +// +// RV64ZIMOP-LABEL: @mopr_0_32( +// RV64ZIMOP-NEXT: entry: +// RV64ZIMOP-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mopr.i32(i32 [[A:%.*]], i32 0) +// RV64ZIMOP-NEXT: ret i32 [[TMP0]] +// +uint32_t mopr_0_32(uint32_t a) { + return __builtin_riscv_mopr_32(a, 0); +} + +// RV32ZIMOP-LABEL: @mopr_31_32( +// RV32ZIMOP-NEXT: entry: +// RV32ZIMOP-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mopr.i32(i32 [[A:%.*]], i32 31) +// RV32ZIMOP-NEXT: ret i32 [[TMP0]] +// +// RV64ZIMOP-LABEL: @mopr_31_32( +// RV64ZIMOP-NEXT: entry: +// RV64ZIMOP-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.mopr.i32(i32 [[A:%.*]], i32 31) +// RV64ZIMOP-NEXT: ret i32 [[TMP0]] +// +uint32_t mopr_31_32(uint32_t a) { + return __builtin_riscv_mopr_32(a, 31); +} + +// RV32ZIMOP-LABEL: @moprr_0_32( +// RV32ZIMOP-NEXT: entry: +// RV32ZIMOP-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.moprr.i32(i32 [[A:%.*]], i32 [[B:%.*]], i32 0) +// RV32ZIMOP-NEXT: ret i32 [[TMP0]] +// +// RV64ZIMOP-LABEL: @moprr_0_32( +// RV64ZIMOP-NEXT: entry: +// RV64ZIMOP-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.moprr.i32(i32 [[A:%.*]], i32 [[B:%.*]], i32 0) +// RV64ZIMOP-NEXT: ret i32 [[TMP0]] +// +uint32_t moprr_0_32(uint32_t a, uint32_t b) { + return __builtin_riscv_moprr_32(a, b, 0); +} + +// RV32ZIMOP-LABEL: @moprr_7_32( +// RV32ZIMOP-NEXT: entry: +// RV32ZIMOP-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.moprr.i32(i32 [[A:%.*]], i32 [[B:%.*]], i32 7) +// RV32ZIMOP-NEXT: ret i32 [[TMP0]] +// +// RV64ZIMOP-LABEL: @moprr_7_32( +// RV64ZIMOP-NEXT: entry: +// RV64ZIMOP-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.moprr.i32(i32 [[A:%.*]], i32 [[B:%.*]], i32 7) +// RV64ZIMOP-NEXT: ret i32 [[TMP0]] +// +uint32_t moprr_7_32(uint32_t a, uint32_t b) { + return __builtin_riscv_moprr_32(a, b, 7); +} +