Skip to content

[RISCV] Implement Clang Builtins for XCValu Extension in CV32E40P #100684

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Oct 1, 2024

Conversation

realqhc
Copy link
Contributor

@realqhc realqhc commented Jul 26, 2024

This commit adds the Clang Builtins, C API header and relevant tests for XCValu extension.

Spec: https://github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributor: @melonedo, @PaoloS02

@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V backend:X86 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:headers Headers provided by Clang, e.g. for intrinsics clang:codegen IR generation bugs: mangling, exceptions, etc. llvm:ir labels Jul 26, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 26, 2024

@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-backend-risc-v

Author: None (realqhc)

Changes

This commit adds the Clang Builtins, C API header and relevant tests for XCValu extension.

Spec: https://github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributor: @melonedo, @PaoloS02


Patch is 42.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/100684.diff

12 Files Affected:

  • (added) clang/include/clang/Basic/BuiltinsRISCVXCV.def (+41)
  • (modified) clang/include/clang/Basic/TargetBuiltins.h (+10)
  • (modified) clang/include/module.modulemap (+1)
  • (modified) clang/lib/Basic/Targets/RISCV.cpp (+5)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+31)
  • (modified) clang/lib/Headers/CMakeLists.txt (+1)
  • (added) clang/lib/Headers/riscv_corev_alu.h (+111)
  • (added) clang/test/CodeGen/RISCV/riscv-xcvalu-c-api.c (+126)
  • (added) clang/test/CodeGen/RISCV/riscv-xcvalu.c (+303)
  • (modified) llvm/include/llvm/IR/IntrinsicsRISCVXCV.td (+18-8)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td (+19-8)
  • (modified) llvm/test/CodeGen/RISCV/xcvalu.ll (+166-56)
diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.def b/clang/include/clang/Basic/BuiltinsRISCVXCV.def
new file mode 100644
index 0000000000000..29c59cdf005d0
--- /dev/null
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.def
@@ -0,0 +1,41 @@
+//==- BuiltinsRISCVXCV.def - RISC-V CORE-V Builtin database ----*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CORE-V-specific builtin function database.  Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
+#   define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
+TARGET_BUILTIN(alu_slet, "ZiZiZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_sletu, "ZiUZiUZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_min, "ZiZiZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_minu, "UZiUZiUZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_max, "ZiZiZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_maxu, "UZiUZiUZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_exths, "Zis", "nc", "xcvalu")
+TARGET_BUILTIN(alu_exthz, "UZiUs", "nc", "xcvalu")
+TARGET_BUILTIN(alu_extbs, "Zic", "nc", "xcvalu")
+TARGET_BUILTIN(alu_extbz, "UZiUc", "nc", "xcvalu")
+
+TARGET_BUILTIN(alu_clip, "ZiZiUZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_clipu, "UZiUZiUZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_addN, "ZiZiUZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_adduN, "UZiUZiUZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_addRN, "ZiZiZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_adduRN, "UZiUZiUZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_subN, "ZiZiUZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_subuN, "UZiUZiUZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_subRN, "ZiZiZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_subuRN, "UZiUZiUZiUc", "nc", "xcvalu")
+
+#undef BUILTIN
+#undef TARGET_BUILTIN
diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h
index 4333830bf34f2..ea3ab9dd1b59b 100644
--- a/clang/include/clang/Basic/TargetBuiltins.h
+++ b/clang/include/clang/Basic/TargetBuiltins.h
@@ -152,12 +152,22 @@ namespace clang {
   };
   }
 
+  namespace RISCVXCV {
+  enum {
+    LastRVVBuiltin = RISCVVector::FirstTSBuiltin - 1,
+#define BUILTIN(ID, TYPE, ATTRS) BI__builtin_riscv_cv_##ID,
+#include "clang/Basic/BuiltinsRISCVXCV.def"
+    FirstTSBuiltin,
+  };
+  }
+
   /// RISCV builtins
   namespace RISCV {
   enum {
     LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
     FirstRVVBuiltin = clang::Builtin::FirstTSBuiltin,
     LastRVVBuiltin = RISCVVector::FirstTSBuiltin - 1,
+    LastXCVBuiltin = RISCVXCV::FirstTSBuiltin - 1,
 #define BUILTIN(ID, TYPE, ATTRS) BI##ID,
 #include "clang/Basic/BuiltinsRISCV.inc"
     LastTSBuiltin
diff --git a/clang/include/module.modulemap b/clang/include/module.modulemap
index 00ecd47d35b62..7f8b721f275c6 100644
--- a/clang/include/module.modulemap
+++ b/clang/include/module.modulemap
@@ -55,6 +55,7 @@ module Clang_Basic {
   textual header "clang/Basic/BuiltinsNEON.def"
   textual header "clang/Basic/BuiltinsNVPTX.def"
   textual header "clang/Basic/BuiltinsPPC.def"
+  textual header "Basic/BuiltinsRISCVXCV.def"
   textual header "clang/Basic/BuiltinsRISCVVector.def"
   textual header "clang/Basic/BuiltinsSME.def"
   textual header "clang/Basic/BuiltinsSVE.def"
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index 41d836330b38c..05016095b88aa 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -231,6 +231,11 @@ static constexpr Builtin::Info BuiltinInfo[] = {
   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
 #include "clang/Basic/BuiltinsRISCVVector.def"
 #define BUILTIN(ID, TYPE, ATTRS)                                               \
+  {"__builtin_riscv_cv_" #ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
+  {"__builtin_riscv_cv_" #ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
+#include "clang/Basic/BuiltinsRISCVXCV.def"
+#define BUILTIN(ID, TYPE, ATTRS)                                               \                                                                               \
   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 0c4d0efb70ea5..d37d1d420e860 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -21901,6 +21901,30 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID,
   return nullptr;
 }
 
+static Value *EmitXCVIntrinsic(CodeGenFunction &CGF, unsigned BuiltinID,
+                               unsigned IntrinsicID,
+                               MutableArrayRef<Value *> Ops,
+                               const CallExpr *E) {
+  llvm::Type *MachineType =
+      llvm::IntegerType::getInt32Ty(CGF.CGM.getLLVMContext());
+  for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) {
+    if (Ops[i]->getType() != MachineType) {
+      QualType type = E->getArg(i)->getType();
+      assert((type->isSignedIntegerType() || type->isUnsignedIntegerType() ||
+              type->isPointerType()) &&
+             "Argument of Core-V builtin must have signed or unsigned integer "
+             "or Pointer type");
+      if (type->isSignedIntegerType()) {
+        Ops[i] = CGF.Builder.CreateSExt(Ops[i], MachineType);
+      } else if ((type->isUnsignedIntegerType())) {
+        Ops[i] = CGF.Builder.CreateZExt(Ops[i], MachineType);
+      }
+    }
+  }
+  llvm::Function *F = CGF.CGM.getIntrinsic(IntrinsicID);
+  return CGF.Builder.CreateCall(F, Ops);
+}
+
 Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
                                              const CallExpr *E,
                                              ReturnValueSlot ReturnValue) {
@@ -22126,6 +22150,13 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     return Store;
   }
 
+// Core-V
+#define BUILTIN(NAME, TYPE, ATTRS)              \
+case RISCVXCV::BI__builtin_riscv_cv_##NAME: \
+  ID = Intrinsic::riscv_cv_##NAME;            \
+  return EmitXCVIntrinsic(*this, BuiltinID, ID, Ops, E);
+#include "clang/Basic/BuiltinsRISCVXCV.def"
+
   // Vector builtins are handled from here.
 #include "clang/Basic/riscv_vector_builtin_cg.inc"
   // SiFive Vector builtins are handled from here.
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index 89fa0ecd45eb4..76a82b845fe23 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -122,6 +122,7 @@ set(riscv_files
   riscv_crypto.h
   riscv_ntlh.h
   sifive_vector.h
+  riscv_corev_alu.h
   )
 
 set(systemz_files
diff --git a/clang/lib/Headers/riscv_corev_alu.h b/clang/lib/Headers/riscv_corev_alu.h
new file mode 100644
index 0000000000000..fd6e7106c0981
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_alu.h
@@ -0,0 +1,111 @@
+/*===---- riscv_corev_alu.h - CORE-V ALU intrinsics ------------------------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_COREV_ALU_H
+#define __RISCV_COREV_ALU_H
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xcvalu)
+
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_abs(long a) { return __builtin_abs(a); }
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_slet(long a, long b) {
+  return __builtin_riscv_cv_alu_slet(a, b);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_sletu(unsigned long a, unsigned long b) {
+  return __builtin_riscv_cv_alu_sletu(a, b);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_min(long a, long b) {
+  return __builtin_riscv_cv_alu_min(a, b);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_minu(unsigned long a, unsigned long b) {
+  return __builtin_riscv_cv_alu_minu(a, b);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_max(long a, long b) {
+  return __builtin_riscv_cv_alu_max(a, b);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_maxu(unsigned long a, unsigned long b) {
+  return __builtin_riscv_cv_alu_maxu(a, b);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_exths(int16_t a) { return __builtin_riscv_cv_alu_exths(a); }
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_exthz(uint16_t a) {
+  return __builtin_riscv_cv_alu_exthz(a);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_extbs(int8_t a) { return __builtin_riscv_cv_alu_extbs(a); }
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_extbz(uint8_t a) {
+  return __builtin_riscv_cv_alu_extbz(a);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_clip(long a, unsigned long b) {
+  return __builtin_riscv_cv_alu_clip(a, b);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_clipu(unsigned long a, unsigned long b) {
+  return __builtin_riscv_cv_alu_clipu(a, b);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_addN(long a, long b, uint8_t shft) {
+  return __builtin_riscv_cv_alu_addN(a, b, shft);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_adduN(unsigned long a, unsigned long b,
+                                   uint8_t shft) {
+  return __builtin_riscv_cv_alu_adduN(a, b, shft);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_addRN(long a, long b, uint8_t shft) {
+  return __builtin_riscv_cv_alu_addRN(a, b, shft);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_adduRN(unsigned long a, unsigned long b,
+                                    uint8_t shft) {
+  return __builtin_riscv_cv_alu_adduRN(a, b, shft);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_subN(long a, long b, uint8_t shft) {
+  return __builtin_riscv_cv_alu_subN(a, b, shft);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_subuN(unsigned long a, unsigned long b,
+                                   uint8_t shft) {
+  return __builtin_riscv_cv_alu_subuN(a, b, shft);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_subRN(long a, long b, uint8_t shft) {
+  return __builtin_riscv_cv_alu_subRN(a, b, shft);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_subuRN(unsigned long a, unsigned long b,
+                                    uint8_t shft) {
+  return __builtin_riscv_cv_alu_subuRN(a, b, shft);
+}
+
+#endif // defined(__riscv_xcvalu)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // define __RISCV_COREV_ALU_H
diff --git a/clang/test/CodeGen/RISCV/riscv-xcvalu-c-api.c b/clang/test/CodeGen/RISCV/riscv-xcvalu-c-api.c
new file mode 100644
index 0000000000000..d5c16fbe3d766
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-xcvalu-c-api.c
@@ -0,0 +1,126 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvalu -emit-llvm %s -o - \
+// RUN:     | FileCheck %s
+
+#include <stdint.h>
+#include <riscv_corev_alu.h>
+
+// CHECK-LABEL: @test_alu_slet
+// CHECK: @llvm.riscv.cv.alu.slet
+int test_alu_slet(int32_t a, int32_t b) {
+  return __riscv_cv_alu_slet(a, b);
+}
+
+// CHECK-LABEL: @test_alu_sletu
+// CHECK: @llvm.riscv.cv.alu.sletu
+int test_alu_sletu(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_sletu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_min
+// CHECK: @llvm.riscv.cv.alu.min
+int test_alu_min(int32_t a, int32_t b) {
+  return __riscv_cv_alu_min(a, b);
+}
+
+// CHECK-LABEL: @test_alu_minu
+// CHECK: @llvm.riscv.cv.alu.minu
+int test_alu_minu(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_minu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_max
+// CHECK: @llvm.riscv.cv.alu.max
+int test_alu_max(int32_t a, int32_t b) {
+  return __riscv_cv_alu_max(a, b);
+}
+
+// CHECK-LABEL: @test_alu_maxu
+// CHECK: @llvm.riscv.cv.alu.maxu
+int test_alu_maxu(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_maxu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_exths
+// CHECK: @llvm.riscv.cv.alu.exths
+int test_alu_exths(int16_t a) {
+  return __riscv_cv_alu_exths(a);
+}
+
+// CHECK-LABEL: @test_alu_exthz
+// CHECK: @llvm.riscv.cv.alu.exthz
+int test_alu_exthz(uint16_t a) {
+  return __riscv_cv_alu_exthz(a);
+}
+
+// CHECK-LABEL: @test_alu_extbs
+// CHECK: @llvm.riscv.cv.alu.extbs
+int test_alu_extbs(int8_t a) {
+  return __riscv_cv_alu_extbs(a);
+}
+
+// CHECK-LABEL: @test_alu_extbz
+// CHECK: @llvm.riscv.cv.alu.extbz
+int test_alu_extbz(uint8_t a) {
+  return __riscv_cv_alu_extbz(a);
+}
+
+// CHECK-LABEL: @test_alu_clip
+// CHECK: @llvm.riscv.cv.alu.clip
+int test_alu_clip(int32_t a) {
+  return __riscv_cv_alu_clip(a, 0);
+}
+
+// CHECK-LABEL: @test_alu_clipu
+// CHECK: @llvm.riscv.cv.alu.clipu
+int test_alu_clipu(uint32_t a) {
+  return __riscv_cv_alu_clipu(a, 0);
+}
+
+// CHECK-LABEL: @test_alu_addN
+// CHECK: @llvm.riscv.cv.alu.addN
+int test_alu_addN(int32_t a, int32_t b) {
+  return __riscv_cv_alu_addN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_adduN
+// CHECK: @llvm.riscv.cv.alu.adduN
+int test_alu_adduN(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_adduN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_addRN
+// CHECK: @llvm.riscv.cv.alu.addRN
+int test_alu_addRN(int32_t a, int32_t b) {
+  return __riscv_cv_alu_addRN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_adduRN
+// CHECK: @llvm.riscv.cv.alu.adduRN
+int test_alu_adduRN(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_adduRN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_subN
+// CHECK: @llvm.riscv.cv.alu.subN
+int test_alu_subN(int32_t a, int32_t b) {
+  return __riscv_cv_alu_subN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_subuN
+// CHECK: @llvm.riscv.cv.alu.subuN
+int test_alu_subuN(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_subuN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_subRN
+// CHECK: @llvm.riscv.cv.alu.subRN
+int test_alu_subRN(int32_t a, int32_t b) {
+  return __riscv_cv_alu_subRN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_subuRN
+// CHECK: @llvm.riscv.cv.alu.subuRN
+int test_alu_subuRN(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_subuRN(a, b, 0);
+}
diff --git a/clang/test/CodeGen/RISCV/riscv-xcvalu.c b/clang/test/CodeGen/RISCV/riscv-xcvalu.c
new file mode 100644
index 0000000000000..a3b8c07f22c81
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-xcvalu.c
@@ -0,0 +1,303 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvalu -emit-llvm %s -o - \
+// RUN:     | FileCheck %s
+
+#include <stdint.h>
+
+// CHECK-LABEL: @test_abs(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP0]], i1 true)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+int test_abs(int a) {
+  return __builtin_abs(a);
+}
+
+// CHECK-LABEL: @test_alu_slet(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.slet(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_slet(int32_t a, int32_t b) {
+  return __builtin_riscv_cv_alu_slet(a, b);
+}
+
+// CHECK-LABEL: @test_alu_sletu(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.sletu(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_sletu(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_alu_sletu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_min(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.min(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_min(int32_t a, int32_t b) {
+  return __builtin_riscv_cv_alu_min(a, b);
+}
+
+// CHECK-LABEL: @test_alu_minu(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.minu(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_minu(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_alu_minu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_max(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.max(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_max(int32_t a, int32_t b) {
+  return __builtin_riscv_cv_alu_max(a, b);
+}
+
+// CHECK-LABEL: @test_alu_maxu(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.maxu(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_maxu(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_alu_maxu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_exths(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
+// CHECK-NEXT:    store i16 [[A:%.*]], ptr [[A_ADDR]], align 2
+// CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[A_ADDR]], align 2
+// CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[TMP0]] to i32
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.exths(i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_exths(int16_t a) {
+  return __builtin_riscv_cv_alu_exths(a);
+}
+
+// CHECK-LABEL: @test_alu_exthz(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
+// CHECK-NEXT:    store i16 [[A:%.*]], ptr [[A_ADDR]], ali...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Jul 26, 2024

@llvm/pr-subscribers-backend-x86

Author: None (realqhc)

Changes

This commit adds the Clang Builtins, C API header and relevant tests for XCValu extension.

Spec: https://github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributor: @melonedo, @PaoloS02


Patch is 42.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/100684.diff

12 Files Affected:

  • (added) clang/include/clang/Basic/BuiltinsRISCVXCV.def (+41)
  • (modified) clang/include/clang/Basic/TargetBuiltins.h (+10)
  • (modified) clang/include/module.modulemap (+1)
  • (modified) clang/lib/Basic/Targets/RISCV.cpp (+5)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+31)
  • (modified) clang/lib/Headers/CMakeLists.txt (+1)
  • (added) clang/lib/Headers/riscv_corev_alu.h (+111)
  • (added) clang/test/CodeGen/RISCV/riscv-xcvalu-c-api.c (+126)
  • (added) clang/test/CodeGen/RISCV/riscv-xcvalu.c (+303)
  • (modified) llvm/include/llvm/IR/IntrinsicsRISCVXCV.td (+18-8)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td (+19-8)
  • (modified) llvm/test/CodeGen/RISCV/xcvalu.ll (+166-56)
diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.def b/clang/include/clang/Basic/BuiltinsRISCVXCV.def
new file mode 100644
index 0000000000000..29c59cdf005d0
--- /dev/null
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.def
@@ -0,0 +1,41 @@
+//==- BuiltinsRISCVXCV.def - RISC-V CORE-V Builtin database ----*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CORE-V-specific builtin function database.  Users of
+// this file must define the BUILTIN macro to make use of this information.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(BUILTIN) && !defined(TARGET_BUILTIN)
+#   define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS)
+#endif
+
+TARGET_BUILTIN(alu_slet, "ZiZiZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_sletu, "ZiUZiUZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_min, "ZiZiZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_minu, "UZiUZiUZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_max, "ZiZiZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_maxu, "UZiUZiUZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_exths, "Zis", "nc", "xcvalu")
+TARGET_BUILTIN(alu_exthz, "UZiUs", "nc", "xcvalu")
+TARGET_BUILTIN(alu_extbs, "Zic", "nc", "xcvalu")
+TARGET_BUILTIN(alu_extbz, "UZiUc", "nc", "xcvalu")
+
+TARGET_BUILTIN(alu_clip, "ZiZiUZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_clipu, "UZiUZiUZi", "nc", "xcvalu")
+TARGET_BUILTIN(alu_addN, "ZiZiUZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_adduN, "UZiUZiUZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_addRN, "ZiZiZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_adduRN, "UZiUZiUZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_subN, "ZiZiUZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_subuN, "UZiUZiUZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_subRN, "ZiZiZiUc", "nc", "xcvalu")
+TARGET_BUILTIN(alu_subuRN, "UZiUZiUZiUc", "nc", "xcvalu")
+
+#undef BUILTIN
+#undef TARGET_BUILTIN
diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h
index 4333830bf34f2..ea3ab9dd1b59b 100644
--- a/clang/include/clang/Basic/TargetBuiltins.h
+++ b/clang/include/clang/Basic/TargetBuiltins.h
@@ -152,12 +152,22 @@ namespace clang {
   };
   }
 
+  namespace RISCVXCV {
+  enum {
+    LastRVVBuiltin = RISCVVector::FirstTSBuiltin - 1,
+#define BUILTIN(ID, TYPE, ATTRS) BI__builtin_riscv_cv_##ID,
+#include "clang/Basic/BuiltinsRISCVXCV.def"
+    FirstTSBuiltin,
+  };
+  }
+
   /// RISCV builtins
   namespace RISCV {
   enum {
     LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1,
     FirstRVVBuiltin = clang::Builtin::FirstTSBuiltin,
     LastRVVBuiltin = RISCVVector::FirstTSBuiltin - 1,
+    LastXCVBuiltin = RISCVXCV::FirstTSBuiltin - 1,
 #define BUILTIN(ID, TYPE, ATTRS) BI##ID,
 #include "clang/Basic/BuiltinsRISCV.inc"
     LastTSBuiltin
diff --git a/clang/include/module.modulemap b/clang/include/module.modulemap
index 00ecd47d35b62..7f8b721f275c6 100644
--- a/clang/include/module.modulemap
+++ b/clang/include/module.modulemap
@@ -55,6 +55,7 @@ module Clang_Basic {
   textual header "clang/Basic/BuiltinsNEON.def"
   textual header "clang/Basic/BuiltinsNVPTX.def"
   textual header "clang/Basic/BuiltinsPPC.def"
+  textual header "Basic/BuiltinsRISCVXCV.def"
   textual header "clang/Basic/BuiltinsRISCVVector.def"
   textual header "clang/Basic/BuiltinsSME.def"
   textual header "clang/Basic/BuiltinsSVE.def"
diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp
index 41d836330b38c..05016095b88aa 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -231,6 +231,11 @@ static constexpr Builtin::Info BuiltinInfo[] = {
   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
 #include "clang/Basic/BuiltinsRISCVVector.def"
 #define BUILTIN(ID, TYPE, ATTRS)                                               \
+  {"__builtin_riscv_cv_" #ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
+#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
+  {"__builtin_riscv_cv_" #ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
+#include "clang/Basic/BuiltinsRISCVXCV.def"
+#define BUILTIN(ID, TYPE, ATTRS)                                               \                                                                               \
   {#ID, TYPE, ATTRS, nullptr, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
 #define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE)                               \
   {#ID, TYPE, ATTRS, FEATURE, HeaderDesc::NO_HEADER, ALL_LANGUAGES},
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 0c4d0efb70ea5..d37d1d420e860 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -21901,6 +21901,30 @@ Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID,
   return nullptr;
 }
 
+static Value *EmitXCVIntrinsic(CodeGenFunction &CGF, unsigned BuiltinID,
+                               unsigned IntrinsicID,
+                               MutableArrayRef<Value *> Ops,
+                               const CallExpr *E) {
+  llvm::Type *MachineType =
+      llvm::IntegerType::getInt32Ty(CGF.CGM.getLLVMContext());
+  for (unsigned i = 0, e = E->getNumArgs(); i != e; i++) {
+    if (Ops[i]->getType() != MachineType) {
+      QualType type = E->getArg(i)->getType();
+      assert((type->isSignedIntegerType() || type->isUnsignedIntegerType() ||
+              type->isPointerType()) &&
+             "Argument of Core-V builtin must have signed or unsigned integer "
+             "or Pointer type");
+      if (type->isSignedIntegerType()) {
+        Ops[i] = CGF.Builder.CreateSExt(Ops[i], MachineType);
+      } else if ((type->isUnsignedIntegerType())) {
+        Ops[i] = CGF.Builder.CreateZExt(Ops[i], MachineType);
+      }
+    }
+  }
+  llvm::Function *F = CGF.CGM.getIntrinsic(IntrinsicID);
+  return CGF.Builder.CreateCall(F, Ops);
+}
+
 Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
                                              const CallExpr *E,
                                              ReturnValueSlot ReturnValue) {
@@ -22126,6 +22150,13 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
     return Store;
   }
 
+// Core-V
+#define BUILTIN(NAME, TYPE, ATTRS)              \
+case RISCVXCV::BI__builtin_riscv_cv_##NAME: \
+  ID = Intrinsic::riscv_cv_##NAME;            \
+  return EmitXCVIntrinsic(*this, BuiltinID, ID, Ops, E);
+#include "clang/Basic/BuiltinsRISCVXCV.def"
+
   // Vector builtins are handled from here.
 #include "clang/Basic/riscv_vector_builtin_cg.inc"
   // SiFive Vector builtins are handled from here.
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index 89fa0ecd45eb4..76a82b845fe23 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -122,6 +122,7 @@ set(riscv_files
   riscv_crypto.h
   riscv_ntlh.h
   sifive_vector.h
+  riscv_corev_alu.h
   )
 
 set(systemz_files
diff --git a/clang/lib/Headers/riscv_corev_alu.h b/clang/lib/Headers/riscv_corev_alu.h
new file mode 100644
index 0000000000000..fd6e7106c0981
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_alu.h
@@ -0,0 +1,111 @@
+/*===---- riscv_corev_alu.h - CORE-V ALU intrinsics ------------------------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_COREV_ALU_H
+#define __RISCV_COREV_ALU_H
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xcvalu)
+
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_abs(long a) { return __builtin_abs(a); }
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_slet(long a, long b) {
+  return __builtin_riscv_cv_alu_slet(a, b);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_sletu(unsigned long a, unsigned long b) {
+  return __builtin_riscv_cv_alu_sletu(a, b);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_min(long a, long b) {
+  return __builtin_riscv_cv_alu_min(a, b);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_minu(unsigned long a, unsigned long b) {
+  return __builtin_riscv_cv_alu_minu(a, b);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_max(long a, long b) {
+  return __builtin_riscv_cv_alu_max(a, b);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_maxu(unsigned long a, unsigned long b) {
+  return __builtin_riscv_cv_alu_maxu(a, b);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_exths(int16_t a) { return __builtin_riscv_cv_alu_exths(a); }
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_exthz(uint16_t a) {
+  return __builtin_riscv_cv_alu_exthz(a);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_extbs(int8_t a) { return __builtin_riscv_cv_alu_extbs(a); }
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_extbz(uint8_t a) {
+  return __builtin_riscv_cv_alu_extbz(a);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_clip(long a, unsigned long b) {
+  return __builtin_riscv_cv_alu_clip(a, b);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_clipu(unsigned long a, unsigned long b) {
+  return __builtin_riscv_cv_alu_clipu(a, b);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_addN(long a, long b, uint8_t shft) {
+  return __builtin_riscv_cv_alu_addN(a, b, shft);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_adduN(unsigned long a, unsigned long b,
+                                   uint8_t shft) {
+  return __builtin_riscv_cv_alu_adduN(a, b, shft);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_addRN(long a, long b, uint8_t shft) {
+  return __builtin_riscv_cv_alu_addRN(a, b, shft);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_adduRN(unsigned long a, unsigned long b,
+                                    uint8_t shft) {
+  return __builtin_riscv_cv_alu_adduRN(a, b, shft);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_subN(long a, long b, uint8_t shft) {
+  return __builtin_riscv_cv_alu_subN(a, b, shft);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_subuN(unsigned long a, unsigned long b,
+                                   uint8_t shft) {
+  return __builtin_riscv_cv_alu_subuN(a, b, shft);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_alu_subRN(long a, long b, uint8_t shft) {
+  return __builtin_riscv_cv_alu_subRN(a, b, shft);
+}
+
+static __inline__ unsigned long __DEFAULT_FN_ATTRS __riscv_cv_alu_subuRN(unsigned long a, unsigned long b,
+                                    uint8_t shft) {
+  return __builtin_riscv_cv_alu_subuRN(a, b, shft);
+}
+
+#endif // defined(__riscv_xcvalu)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // define __RISCV_COREV_ALU_H
diff --git a/clang/test/CodeGen/RISCV/riscv-xcvalu-c-api.c b/clang/test/CodeGen/RISCV/riscv-xcvalu-c-api.c
new file mode 100644
index 0000000000000..d5c16fbe3d766
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-xcvalu-c-api.c
@@ -0,0 +1,126 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvalu -emit-llvm %s -o - \
+// RUN:     | FileCheck %s
+
+#include <stdint.h>
+#include <riscv_corev_alu.h>
+
+// CHECK-LABEL: @test_alu_slet
+// CHECK: @llvm.riscv.cv.alu.slet
+int test_alu_slet(int32_t a, int32_t b) {
+  return __riscv_cv_alu_slet(a, b);
+}
+
+// CHECK-LABEL: @test_alu_sletu
+// CHECK: @llvm.riscv.cv.alu.sletu
+int test_alu_sletu(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_sletu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_min
+// CHECK: @llvm.riscv.cv.alu.min
+int test_alu_min(int32_t a, int32_t b) {
+  return __riscv_cv_alu_min(a, b);
+}
+
+// CHECK-LABEL: @test_alu_minu
+// CHECK: @llvm.riscv.cv.alu.minu
+int test_alu_minu(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_minu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_max
+// CHECK: @llvm.riscv.cv.alu.max
+int test_alu_max(int32_t a, int32_t b) {
+  return __riscv_cv_alu_max(a, b);
+}
+
+// CHECK-LABEL: @test_alu_maxu
+// CHECK: @llvm.riscv.cv.alu.maxu
+int test_alu_maxu(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_maxu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_exths
+// CHECK: @llvm.riscv.cv.alu.exths
+int test_alu_exths(int16_t a) {
+  return __riscv_cv_alu_exths(a);
+}
+
+// CHECK-LABEL: @test_alu_exthz
+// CHECK: @llvm.riscv.cv.alu.exthz
+int test_alu_exthz(uint16_t a) {
+  return __riscv_cv_alu_exthz(a);
+}
+
+// CHECK-LABEL: @test_alu_extbs
+// CHECK: @llvm.riscv.cv.alu.extbs
+int test_alu_extbs(int8_t a) {
+  return __riscv_cv_alu_extbs(a);
+}
+
+// CHECK-LABEL: @test_alu_extbz
+// CHECK: @llvm.riscv.cv.alu.extbz
+int test_alu_extbz(uint8_t a) {
+  return __riscv_cv_alu_extbz(a);
+}
+
+// CHECK-LABEL: @test_alu_clip
+// CHECK: @llvm.riscv.cv.alu.clip
+int test_alu_clip(int32_t a) {
+  return __riscv_cv_alu_clip(a, 0);
+}
+
+// CHECK-LABEL: @test_alu_clipu
+// CHECK: @llvm.riscv.cv.alu.clipu
+int test_alu_clipu(uint32_t a) {
+  return __riscv_cv_alu_clipu(a, 0);
+}
+
+// CHECK-LABEL: @test_alu_addN
+// CHECK: @llvm.riscv.cv.alu.addN
+int test_alu_addN(int32_t a, int32_t b) {
+  return __riscv_cv_alu_addN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_adduN
+// CHECK: @llvm.riscv.cv.alu.adduN
+int test_alu_adduN(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_adduN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_addRN
+// CHECK: @llvm.riscv.cv.alu.addRN
+int test_alu_addRN(int32_t a, int32_t b) {
+  return __riscv_cv_alu_addRN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_adduRN
+// CHECK: @llvm.riscv.cv.alu.adduRN
+int test_alu_adduRN(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_adduRN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_subN
+// CHECK: @llvm.riscv.cv.alu.subN
+int test_alu_subN(int32_t a, int32_t b) {
+  return __riscv_cv_alu_subN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_subuN
+// CHECK: @llvm.riscv.cv.alu.subuN
+int test_alu_subuN(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_subuN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_subRN
+// CHECK: @llvm.riscv.cv.alu.subRN
+int test_alu_subRN(int32_t a, int32_t b) {
+  return __riscv_cv_alu_subRN(a, b, 0);
+}
+
+// CHECK-LABEL: @test_alu_subuRN
+// CHECK: @llvm.riscv.cv.alu.subuRN
+int test_alu_subuRN(uint32_t a, uint32_t b) {
+  return __riscv_cv_alu_subuRN(a, b, 0);
+}
diff --git a/clang/test/CodeGen/RISCV/riscv-xcvalu.c b/clang/test/CodeGen/RISCV/riscv-xcvalu.c
new file mode 100644
index 0000000000000..a3b8c07f22c81
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-xcvalu.c
@@ -0,0 +1,303 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvalu -emit-llvm %s -o - \
+// RUN:     | FileCheck %s
+
+#include <stdint.h>
+
+// CHECK-LABEL: @test_abs(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP0]], i1 true)
+// CHECK-NEXT:    ret i32 [[TMP1]]
+//
+int test_abs(int a) {
+  return __builtin_abs(a);
+}
+
+// CHECK-LABEL: @test_alu_slet(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.slet(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_slet(int32_t a, int32_t b) {
+  return __builtin_riscv_cv_alu_slet(a, b);
+}
+
+// CHECK-LABEL: @test_alu_sletu(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.sletu(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_sletu(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_alu_sletu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_min(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.min(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_min(int32_t a, int32_t b) {
+  return __builtin_riscv_cv_alu_min(a, b);
+}
+
+// CHECK-LABEL: @test_alu_minu(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.minu(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_minu(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_alu_minu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_max(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.max(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_max(int32_t a, int32_t b) {
+  return __builtin_riscv_cv_alu_max(a, b);
+}
+
+// CHECK-LABEL: @test_alu_maxu(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.maxu(i32 [[TMP0]], i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_maxu(uint32_t a, uint32_t b) {
+  return __builtin_riscv_cv_alu_maxu(a, b);
+}
+
+// CHECK-LABEL: @test_alu_exths(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
+// CHECK-NEXT:    store i16 [[A:%.*]], ptr [[A_ADDR]], align 2
+// CHECK-NEXT:    [[TMP0:%.*]] = load i16, ptr [[A_ADDR]], align 2
+// CHECK-NEXT:    [[TMP1:%.*]] = sext i16 [[TMP0]] to i32
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.alu.exths(i32 [[TMP1]])
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int test_alu_exths(int16_t a) {
+  return __builtin_riscv_cv_alu_exths(a);
+}
+
+// CHECK-LABEL: @test_alu_exthz(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[A_ADDR:%.*]] = alloca i16, align 2
+// CHECK-NEXT:    store i16 [[A:%.*]], ptr [[A_ADDR]], ali...
[truncated]

@realqhc realqhc requested a review from topperc July 26, 2024 02:53
@realqhc realqhc self-assigned this Jul 26, 2024
Copy link

github-actions bot commented Jul 26, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@realqhc realqhc force-pushed the alu-clang-builtins branch from 5d0eb64 to a989acc Compare July 26, 2024 03:17
@realqhc realqhc closed this Jul 26, 2024
@realqhc realqhc reopened this Jul 26, 2024
@realqhc realqhc force-pushed the alu-clang-builtins branch from a989acc to d2169ca Compare July 26, 2024 04:03
@@ -59,16 +59,26 @@ let TargetPrefix = "riscv" in {
[IntrNoMem, IntrWillReturn, IntrSpeculatable,
ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<2>>]>;

def int_riscv_cv_alu_slet : ScalarCoreVAluGprGprIntrinsic;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need builtins or intrinsics for slet? We don't have builtins for slt/sltu.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @topperc

There are a few things going on here.

  1. The naming of the corresponding instructions in the CORE-V ISA extension was changed from slet to sle, and sletu to sleu. The CORE-V standard for builtins has not yet been updated to reflect this change. This needs to be fixed through OpenHW group's standardization processes (@PaoloS02 is leading this inside OpenHW Group).

  2. These instructions only exist for "less than or equal", there are no equivalents for other comparison predicates, hence just these two builtins mapping to the instructions.

  3. LLVM and GCC for CORE-V are intended to be equivalent, and in GCC, having the builtin to generate the instruction is more efficient than using inline assembler. First the dataflow through the instruction is explicit, secondly the pattern for the functionality is exposed to GCC, potentially allowing the instruction to be generated automatically in other circumstances.

So in summary i) it's there because the CORE-V standard for builtins says it should be and ii) it's there to match GCC behavior.

Hope this is helpful.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @topperc

There are a few things going on here.

  1. The naming of the corresponding instructions in the CORE-V ISA extension was changed from slet to sle, and sletu to sleu. The CORE-V standard for builtins has not yet been updated to reflect this change. This needs to be fixed through OpenHW group's standardization processes (@PaoloS02 is leading this inside OpenHW Group).

  2. These instructions only exist for "less than or equal", there are no equivalents for other comparison predicates, hence just these two builtins mapping to the instructions.

I was referring to the stand comparisons. We don't have builtins for writing slt, we expect the programmer to write (a< b) and the backend will figure it out. slte can be automatically selected from (a<=b). Why do we need a builtin too?

  1. LLVM and GCC for CORE-V are intended to be equivalent, and in GCC, having the builtin to generate the instruction is more efficient than using inline assembler. First the dataflow through the instruction is explicit, secondly the pattern for the functionality is exposed to GCC, potentially allowing the instruction to be generated automatically in other circumstances.

Since gcc already has the builtin, I guess we have to be source compatible. Would it be ok to map the builtin to (zext (icmp sle a,b) in IR and let the middle end and backend treat it like any other compare?

So in summary i) it's there because the CORE-V standard for builtins says it should be and ii) it's there to match GCC behavior.

Hope this is helpful.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it too late to remove the builtin? I can't imagine there's much software out there actually using these that would be a pain to change.

Copy link
Collaborator

@jrtc27 jrtc27 Aug 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Especially if they're already being renamed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also note that conversations like this is why standard RISC-V builtins go through a review process seen by developers of both toolchains. I would encourage CORE-V to do the same if they don't want to be surprised by pushback for things that developers of certain toolchains think don't make sense.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @topperc
There are a few things going on here.

@topperc Thanks for this. Apologies if my original comment was a bit clumsy. I was trying to explain where we were, not where we should go!

  1. These instructions only exist for "less than or equal", there are no equivalents for other comparison predicates, hence just these two builtins mapping to the instructions.

I was referring to the stand comparisons. We don't have builtins for writing slt, we expect the programmer to write (a< b) and the backend will figure it out. slte can be automatically selected from (a<=b). Why do we need a builtin too?

I understand.

  1. LLVM and GCC for CORE-V are intended to be equivalent, and in GCC, having the builtin to generate the instruction is more efficient than using inline assembler. First the dataflow through the instruction is explicit, secondly the pattern for the functionality is exposed to GCC, potentially allowing the instruction to be generated automatically in other circumstances.

Since gcc already has the builtin, I guess we have to be source compatible. Would it be ok to map the builtin to (zext (icmp sle a,b) in IR and let the middle end and backend treat it like any other compare?

This is fine. We just want to make sure that any legacy code written for GCC is not too painful to switch to LLVM for the owners.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it too late to remove the builtin? I can't imagine there's much software out there actually using these that would be a pain to change.

@jrtc27 Thanks for the feedback. The problem with an open source core, is that you don't know who has picked it up and adopted it. This core is particularly attractive because of its verification status. I have come across one very large multinational (not an OpenHW member) using the core, without having made any public declaration that this is the core they are using.

We could try dropping it and see if anyone complains.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also note that conversations like this is why standard RISC-V builtins go through a review process seen by developers of both toolchains. I would encourage CORE-V to do the same if they don't want to be surprised by pushback for things that developers of certain toolchains think don't make sense.

@jrtc27 We have to put our hands up on this one. For a long time the CORE-V and its ancestors have only had GCC tool chains, so the engagement was with that community. The LLVM implementation is newer, but we should have reached out early in the project.

How would you suggest we progress given where we are?

@@ -59,16 +59,26 @@ let TargetPrefix = "riscv" in {
[IntrNoMem, IntrWillReturn, IntrSpeculatable,
ImmArg<ArgIndex<1>>, ImmArg<ArgIndex<2>>]>;

def int_riscv_cv_alu_slet : ScalarCoreVAluGprGprIntrinsic;
def int_riscv_cv_alu_sletu : ScalarCoreVAluGprGprIntrinsic;
def int_riscv_cv_alu_min : ScalarCoreVAluGprGprIntrinsic;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need builtins for max/min. You can express those directly in C and InstCombine will make llvm.min/max intrinsics.

def int_riscv_cv_alu_minu : ScalarCoreVAluGprGprIntrinsic;
def int_riscv_cv_alu_max : ScalarCoreVAluGprGprIntrinsic;
def int_riscv_cv_alu_maxu : ScalarCoreVAluGprGprIntrinsic;
def int_riscv_cv_alu_exths : ScalarCoreVAluGprIntrinsic;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The extends can be directly expressed in IR with shifts or truncate+extend. I don't think we need intrinsics.

enum {
LastRVVBuiltin = RISCVVector::FirstTSBuiltin - 1,
#define BUILTIN(ID, TYPE, ATTRS) BI__builtin_riscv_cv_##ID,
#include "clang/Basic/BuiltinsRISCVXCV.def"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we include BuiltinsRISCVXCV.def from BuiltinsRISCV.def and not create a new RISCVXCV namespace? RVV it separated because we use FirstRVVBuiltin and LastRVVBuiltin to catch all RVV builtins for some code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no BuiltinsRISCV.def and I can't find a way to make it work like BuiltinRISCVVector.def where rvv and sifive builtins can be in separate files (without modifying BuiltinsRISCV.td).
I have rewrite BuiltinsRISCVXCV.def in the same format as BuiltinsRISCV.td and included it in BuiltinsRISCV.td for now, I'm willing to explore further if there is better solution.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot that BuiltinsRISCV.def had been migrated to BuiltinsRISCV.td

//===----------------------------------------------------------------------===//
// XCValu extension.
//===----------------------------------------------------------------------===//
def alu_slet : RISCXCVBuiltin<"int(int, int)", "xcvalu">;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did the intrinsics keep the 't' in their name even though the instruction was renamed here openhwgroup/cv32e40p#833?

Copy link
Contributor Author

@realqhc realqhc Sep 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will update the intrinsics accordingly after the documentation is renamed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather see them deleted. If it's possible to rename them then it's possible to remove them outright and require people to write the trivial standard C equivalent. They serve zero purpose that I can see.

@@ -792,17 +792,18 @@ let Predicates = [HasVendorXCValu, IsRV32], AddedComplexity = 1 in {
def : Pat<(sext_inreg (XLenVT GPR:$rs1), i16), (CV_EXTHS GPR:$rs1)>;
def : Pat<(sext_inreg (XLenVT GPR:$rs1), i8), (CV_EXTBS GPR:$rs1)>;
def : Pat<(and (XLenVT GPR:$rs1), 0xffff), (CV_EXTHZ GPR:$rs1)>;
def : Pat<(and (XLenVT GPR:$rs1), 0xff), (CV_EXTBZ GPR:$rs1)>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is CV_EXTBZ better than ANDI?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry for the late reply. I have raised the question to openhardware group and the answer is, for CV32E40P extension enabled CPUs,cv.extbz should replace andi when possible, but the performance comparison is not available right now.

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@realqhc realqhc merged commit 00128a2 into llvm:main Oct 1, 2024
8 checks passed
@realqhc realqhc deleted the alu-clang-builtins branch October 1, 2024 01:22
@llvm-ci
Copy link
Collaborator

llvm-ci commented Oct 1, 2024

LLVM Buildbot has detected a new failure on builder lld-x86_64-win running on as-worker-93 while building clang,llvm at step 7 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/146/builds/1285

Here is the relevant piece of the build log for the reference
Step 7 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM-Unit :: Support/./SupportTests.exe/35/87' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe-LLVM-Unit-18460-35-87.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=87 GTEST_SHARD_INDEX=35 C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe
--

Script:
--
C:\a\lld-x86_64-win\build\unittests\Support\.\SupportTests.exe --gtest_filter=ProgramEnvTest.CreateProcessLongPath
--
C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(160): error: Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp(163): error: fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied



C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:160
Expected equality of these values:
  0
  RC
    Which is: -2

C:\a\lld-x86_64-win\llvm-project\llvm\unittests\Support\ProgramTest.cpp:163
fs::remove(Twine(LongPath)): did not return errc::success.
error number: 13
error message: permission denied




********************


Sterling-Augustine pushed a commit to Sterling-Augustine/llvm-project that referenced this pull request Oct 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V backend:X86 clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:headers Headers provided by Clang, e.g. for intrinsics clang Clang issues not falling into any other category llvm:ir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants