From 4ee3cbce0032f57c30692654be160e2745955f04 Mon Sep 17 00:00:00 2001 From: Jim Lin Date: Mon, 5 May 2025 13:58:59 +0800 Subject: [PATCH 1/2] [RISCV] Implement Clang Builtins for XAndesPerf Extension This patch adds the Clang builtins for byte comparision instructions in XAndesPerf Extension. These instructions are hardly generated by compiler. So we provide the Clang builtins for the user. --- clang/include/clang/Basic/BuiltinsRISCV.td | 5 + .../clang/Basic/BuiltinsRISCVXAndes.td | 29 ++++ clang/lib/CodeGen/TargetBuiltins/RISCV.cpp | 18 ++ clang/lib/Headers/CMakeLists.txt | 1 + clang/lib/Headers/riscv_nds.h | 47 ++++++ .../CodeGen/RISCV/riscv-xandesperf-c-api.c | 159 ++++++++++++++++++ clang/test/CodeGen/RISCV/riscv-xandesperf.c | 109 ++++++++++++ llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td | 14 ++ llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td | 11 ++ llvm/test/CodeGen/RISCV/rv32xandesperf.ll | 47 ++++++ llvm/test/CodeGen/RISCV/rv64xandesperf.ll | 47 ++++++ 11 files changed, 487 insertions(+) create mode 100644 clang/include/clang/Basic/BuiltinsRISCVXAndes.td create mode 100644 clang/lib/Headers/riscv_nds.h create mode 100644 clang/test/CodeGen/RISCV/riscv-xandesperf-c-api.c create mode 100644 clang/test/CodeGen/RISCV/riscv-xandesperf.c diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td index b2cd5648e008f..5927eaf80d57a 100644 --- a/clang/include/clang/Basic/BuiltinsRISCV.td +++ b/clang/include/clang/Basic/BuiltinsRISCV.td @@ -157,3 +157,8 @@ def pause : RISCVBuiltin<"void()">; // XCV extensions. //===----------------------------------------------------------------------===// include "clang/Basic/BuiltinsRISCVXCV.td" + +//===----------------------------------------------------------------------===// +// XAndes extensions. +//===----------------------------------------------------------------------===// +include "clang/Basic/BuiltinsRISCVXAndes.td" diff --git a/clang/include/clang/Basic/BuiltinsRISCVXAndes.td b/clang/include/clang/Basic/BuiltinsRISCVXAndes.td new file mode 100644 index 0000000000000..8ebcc18889d6c --- /dev/null +++ b/clang/include/clang/Basic/BuiltinsRISCVXAndes.td @@ -0,0 +1,29 @@ +//==- BuiltinsRISCVXAndes.td - RISC-V Andes 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 Andes-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +class RISCVXAndesBuiltin : TargetBuiltin { + let Spellings = ["__builtin_riscv_nds_" # NAME]; + let Prototype = prototype; + let Features = features; +} + +let Attributes = [NoThrow, Const] in { +//===----------------------------------------------------------------------===// +// XAndesPerf extension. +//===----------------------------------------------------------------------===// + +def ffb : RISCVXAndesBuiltin<"long int(unsigned long int, unsigned long int)", "xandesperf">; +def ffzmism : RISCVXAndesBuiltin<"long int(unsigned long int, unsigned long int)", "xandesperf">; +def ffmism : RISCVXAndesBuiltin<"long int(unsigned long int, unsigned long int)", "xandesperf">; +def flmism : RISCVXAndesBuiltin<"long int(unsigned long int, unsigned long int)", "xandesperf">; +} // Attributes = [NoThrow, Const] diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp index 89e3f6f203df3..48a497b32a4a6 100644 --- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp @@ -413,6 +413,24 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, ID = Intrinsic::riscv_cv_alu_subuRN; break; + // XAndesPerf + case RISCV::BI__builtin_riscv_nds_ffb: + IntrinsicTypes = {ResultType}; + ID = Intrinsic::riscv_nds_ffb; + break; + case RISCV::BI__builtin_riscv_nds_ffzmism: + IntrinsicTypes = {ResultType}; + ID = Intrinsic::riscv_nds_ffzmism; + break; + case RISCV::BI__builtin_riscv_nds_ffmism: + IntrinsicTypes = {ResultType}; + ID = Intrinsic::riscv_nds_ffmism; + break; + case RISCV::BI__builtin_riscv_nds_flmism: + IntrinsicTypes = {ResultType}; + ID = Intrinsic::riscv_nds_flmism; + break; + // Vector builtins are handled from here. #include "clang/Basic/riscv_vector_builtin_cg.inc" diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index c96d209c1fc0c..44e2d4b1174c0 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -126,6 +126,7 @@ set(ppc_htm_files set(riscv_files riscv_bitmanip.h riscv_corev_alu.h + riscv_nds.h riscv_crypto.h riscv_ntlh.h sifive_vector.h diff --git a/clang/lib/Headers/riscv_nds.h b/clang/lib/Headers/riscv_nds.h new file mode 100644 index 0000000000000..dcce943f59b71 --- /dev/null +++ b/clang/lib/Headers/riscv_nds.h @@ -0,0 +1,47 @@ +/*===---- riscv_nds.h - Andes 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_NDS_H +#define __RISCV_NDS_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(__riscv_xandesperf) + +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__)) + +static __inline__ long __DEFAULT_FN_ATTRS __riscv_nds_ffb(unsigned long a, + unsigned long b) { + return __builtin_riscv_nds_ffb(a, b); +} + +static __inline__ long __DEFAULT_FN_ATTRS __riscv_nds_ffzmism(unsigned long a, + unsigned long b) { + return __builtin_riscv_nds_ffzmism(a, b); +} + +static __inline__ long __DEFAULT_FN_ATTRS __riscv_nds_ffmism(unsigned long a, + unsigned long b) { + return __builtin_riscv_nds_ffmism(a, b); +} + +static __inline__ long __DEFAULT_FN_ATTRS __riscv_nds_flmism(unsigned long a, + unsigned long b) { + return __builtin_riscv_nds_flmism(a, b); +} + +#endif // defined(__riscv_nds) + +#if defined(__cplusplus) +} +#endif + +#endif // define __RISCV_NDS_H diff --git a/clang/test/CodeGen/RISCV/riscv-xandesperf-c-api.c b/clang/test/CodeGen/RISCV/riscv-xandesperf-c-api.c new file mode 100644 index 0000000000000..ab872d13cc1ea --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-xandesperf-c-api.c @@ -0,0 +1,159 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple riscv32 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-RV32 +// RUN: %clang_cc1 -triple riscv64 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-RV64 + +#include + +// CHECK-RV32-LABEL: @test_ffb( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[A_ADDR_I:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR_I:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4 +// CHECK-RV32-NEXT: store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP4:%.*]] = call i32 @llvm.riscv.nds.ffb.i32(i32 [[TMP2]], i32 [[TMP3]]) +// CHECK-RV32-NEXT: ret i32 [[TMP4]] +// +// CHECK-RV64-LABEL: @test_ffb( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[A_ADDR_I:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR_I:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[TMP0]], ptr [[A_ADDR_I]], align 8 +// CHECK-RV64-NEXT: store i64 [[TMP1]], ptr [[B_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = load i64, ptr [[A_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = load i64, ptr [[B_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP4:%.*]] = call i64 @llvm.riscv.nds.ffb.i64(i64 [[TMP2]], i64 [[TMP3]]) +// CHECK-RV64-NEXT: ret i64 [[TMP4]] +// +long test_ffb(unsigned long a, unsigned long b) { + return __riscv_nds_ffb(a, b); +} + +// CHECK-RV32-LABEL: @test_ffzmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[A_ADDR_I:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR_I:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4 +// CHECK-RV32-NEXT: store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP4:%.*]] = call i32 @llvm.riscv.nds.ffzmism.i32(i32 [[TMP2]], i32 [[TMP3]]) +// CHECK-RV32-NEXT: ret i32 [[TMP4]] +// +// CHECK-RV64-LABEL: @test_ffzmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[A_ADDR_I:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR_I:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[TMP0]], ptr [[A_ADDR_I]], align 8 +// CHECK-RV64-NEXT: store i64 [[TMP1]], ptr [[B_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = load i64, ptr [[A_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = load i64, ptr [[B_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP4:%.*]] = call i64 @llvm.riscv.nds.ffzmism.i64(i64 [[TMP2]], i64 [[TMP3]]) +// CHECK-RV64-NEXT: ret i64 [[TMP4]] +// +long test_ffzmism(unsigned long a, unsigned long b) { + return __riscv_nds_ffzmism(a, b); +} + +// CHECK-RV32-LABEL: @test_ffmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[A_ADDR_I:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR_I:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4 +// CHECK-RV32-NEXT: store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP4:%.*]] = call i32 @llvm.riscv.nds.ffmism.i32(i32 [[TMP2]], i32 [[TMP3]]) +// CHECK-RV32-NEXT: ret i32 [[TMP4]] +// +// CHECK-RV64-LABEL: @test_ffmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[A_ADDR_I:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR_I:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[TMP0]], ptr [[A_ADDR_I]], align 8 +// CHECK-RV64-NEXT: store i64 [[TMP1]], ptr [[B_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = load i64, ptr [[A_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = load i64, ptr [[B_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP4:%.*]] = call i64 @llvm.riscv.nds.ffmism.i64(i64 [[TMP2]], i64 [[TMP3]]) +// CHECK-RV64-NEXT: ret i64 [[TMP4]] +// +long test_ffmism(unsigned long a, unsigned long b) { + return __riscv_nds_ffmism(a, b); +} + +// CHECK-RV32-LABEL: @test_flmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[A_ADDR_I:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR_I:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4 +// CHECK-RV32-NEXT: store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR_I]], align 4 +// CHECK-RV32-NEXT: [[TMP4:%.*]] = call i32 @llvm.riscv.nds.flmism.i32(i32 [[TMP2]], i32 [[TMP3]]) +// CHECK-RV32-NEXT: ret i32 [[TMP4]] +// +// CHECK-RV64-LABEL: @test_flmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[A_ADDR_I:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR_I:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[TMP0]], ptr [[A_ADDR_I]], align 8 +// CHECK-RV64-NEXT: store i64 [[TMP1]], ptr [[B_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = load i64, ptr [[A_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP3:%.*]] = load i64, ptr [[B_ADDR_I]], align 8 +// CHECK-RV64-NEXT: [[TMP4:%.*]] = call i64 @llvm.riscv.nds.flmism.i64(i64 [[TMP2]], i64 [[TMP3]]) +// CHECK-RV64-NEXT: ret i64 [[TMP4]] +// +long test_flmism(unsigned long a, unsigned long b) { + return __riscv_nds_flmism(a, b); +} diff --git a/clang/test/CodeGen/RISCV/riscv-xandesperf.c b/clang/test/CodeGen/RISCV/riscv-xandesperf.c new file mode 100644 index 0000000000000..d4273b295ed46 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-xandesperf.c @@ -0,0 +1,109 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple riscv32 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-RV32 +// RUN: %clang_cc1 -triple riscv64 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: | FileCheck %s --check-prefix=CHECK-RV64 + +// CHECK-RV32-LABEL: @test_ffb( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.nds.ffb.i32(i32 [[TMP0]], i32 [[TMP1]]) +// CHECK-RV32-NEXT: ret i32 [[TMP2]] +// +// CHECK-RV64-LABEL: @test_ffb( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = call i64 @llvm.riscv.nds.ffb.i64(i64 [[TMP0]], i64 [[TMP1]]) +// CHECK-RV64-NEXT: ret i64 [[TMP2]] +// +long test_ffb(unsigned long a, unsigned long b) { + return __builtin_riscv_nds_ffb(a, b); +} + +// CHECK-RV32-LABEL: @test_ffzmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.nds.ffzmism.i32(i32 [[TMP0]], i32 [[TMP1]]) +// CHECK-RV32-NEXT: ret i32 [[TMP2]] +// +// CHECK-RV64-LABEL: @test_ffzmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = call i64 @llvm.riscv.nds.ffzmism.i64(i64 [[TMP0]], i64 [[TMP1]]) +// CHECK-RV64-NEXT: ret i64 [[TMP2]] +// +long test_ffzmism(unsigned long a, unsigned long b) { + return __builtin_riscv_nds_ffzmism(a, b); +} + +// CHECK-RV32-LABEL: @test_ffmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.nds.ffmism.i32(i32 [[TMP0]], i32 [[TMP1]]) +// CHECK-RV32-NEXT: ret i32 [[TMP2]] +// +// CHECK-RV64-LABEL: @test_ffmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = call i64 @llvm.riscv.nds.ffmism.i64(i64 [[TMP0]], i64 [[TMP1]]) +// CHECK-RV64-NEXT: ret i64 [[TMP2]] +// +long test_ffmism(unsigned long a, unsigned long b) { + return __builtin_riscv_nds_ffmism(a, b); +} + +// CHECK-RV32-LABEL: @test_flmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 +// CHECK-RV32-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.nds.flmism.i32(i32 [[TMP0]], i32 [[TMP1]]) +// CHECK-RV32-NEXT: ret i32 [[TMP2]] +// +// CHECK-RV64-LABEL: @test_flmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 +// CHECK-RV64-NEXT: [[TMP2:%.*]] = call i64 @llvm.riscv.nds.flmism.i64(i64 [[TMP0]], i64 [[TMP1]]) +// CHECK-RV64-NEXT: ret i64 [[TMP2]] +// +long test_flmism(unsigned long a, unsigned long b) { + return __builtin_riscv_nds_flmism(a, b); +} diff --git a/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td b/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td index 92a07e9a6a5d0..0fa7b4d60ace0 100644 --- a/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td @@ -11,6 +11,20 @@ //===----------------------------------------------------------------------===// let TargetPrefix = "riscv" in { + // Andes Performance Extension + def int_riscv_nds_ffb : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + def int_riscv_nds_ffzmism : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + def int_riscv_nds_ffmism : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + def int_riscv_nds_flmism : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + // Andes Vector BFloat16 Conversion Extension def int_riscv_nds_vfwcvt_s_bf16 : RISCVConversionUnMasked; def int_riscv_nds_vfncvt_bf16_s : RISCVConversionUnMaskedRoundingMode; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td index f2a1866510ded..d54d934fe3ed4 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td @@ -642,6 +642,17 @@ def : Sh2AddPat; def : Sh3AddPat; } // Predicates = [HasVendorXAndesPerf, IsRV64] +let Predicates = [HasVendorXAndesPerf] in { +def : Pat<(XLenVT (int_riscv_nds_ffb (XLenVT GPR:$rs1), (XLenVT GPR:$rs2))), + (NDS_FFB GPR:$rs1, GPR:$rs2)>; +def : Pat<(XLenVT (int_riscv_nds_ffzmism (XLenVT GPR:$rs1), (XLenVT GPR:$rs2))), + (NDS_FFZMISM GPR:$rs1, GPR:$rs2)>; +def : Pat<(XLenVT (int_riscv_nds_ffmism (XLenVT GPR:$rs1), (XLenVT GPR:$rs2))), + (NDS_FFMISM GPR:$rs1, GPR:$rs2)>; +def : Pat<(XLenVT (int_riscv_nds_flmism (XLenVT GPR:$rs1), (XLenVT GPR:$rs2))), + (NDS_FLMISM GPR:$rs1, GPR:$rs2)>; +} // Predicates = [HasVendorXAndesPerf] + let Predicates = [HasVendorXAndesVBFHCvt] in { defm PseudoNDS_VFWCVT_S_BF16 : VPseudoVWCVT_S_BF16; defm PseudoNDS_VFNCVT_BF16_S : VPseudoVNCVT_BF16_S; diff --git a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll index 5cabb8c53e261..4c8fd5617abc1 100644 --- a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll +++ b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll @@ -492,3 +492,50 @@ define i64 @sexti32_i64_2(i32 %a) { %1 = sext i32 %a to i64 ret i64 %1 } + +; NDS.FFB/NDS.FFZMISM/NDS.FFMISM/NDS.FLMISM + +declare i32 @llvm.riscv.nds.ffb.i32(i32, i32) +declare i32 @llvm.riscv.nds.ffzmism.i32(i32, i32) +declare i32 @llvm.riscv.nds.ffmism.i32(i32, i32) +declare i32 @llvm.riscv.nds.flmism.i32(i32, i32) + +define i32 @ffb(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: ffb: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffb a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.riscv.nds.ffb.i32(i32 %a, i32 %b) + ret i32 %0 +} + +define i32 @ffzmism(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: ffzmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffzmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.riscv.nds.ffzmism.i32(i32 %a, i32 %b) + ret i32 %0 +} + +define i32 @ffmism(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: ffmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.riscv.nds.ffmism.i32(i32 %a, i32 %b) + ret i32 %0 +} + +define i32 @flmism(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: flmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.flmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.riscv.nds.flmism.i32(i32 %a, i32 %b) + ret i32 %0 +} diff --git a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll index 98cda42665169..09815b81c1a48 100644 --- a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll +++ b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll @@ -389,3 +389,50 @@ define i64 @sexti32_i64_2(i32 signext %a) { %1 = sext i32 %a to i64 ret i64 %1 } + +; NDS.FFB/NDS.FFZMISM/NDS.FFMISM/NDS.FLMISM + +declare i64 @llvm.riscv.nds.ffb.i64(i64, i64) +declare i64 @llvm.riscv.nds.ffzmism.i64(i64, i64) +declare i64 @llvm.riscv.nds.ffmism.i64(i64, i64) +declare i64 @llvm.riscv.nds.flmism.i64(i64, i64) + +define i64 @ffb(i64 %a, i64 %b) nounwind { +; CHECK-LABEL: ffb: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffb a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.riscv.nds.ffb.i64(i64 %a, i64 %b) + ret i64 %0 +} + +define i64 @ffzmism(i64 %a, i64 %b) nounwind { +; CHECK-LABEL: ffzmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffzmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.riscv.nds.ffzmism.i64(i64 %a, i64 %b) + ret i64 %0 +} + +define i64 @ffmism(i64 %a, i64 %b) nounwind { +; CHECK-LABEL: ffmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.riscv.nds.ffmism.i64(i64 %a, i64 %b) + ret i64 %0 +} + +define i64 @flmism(i64 %a, i64 %b) nounwind { +; CHECK-LABEL: flmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.flmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.riscv.nds.flmism.i64(i64 %a, i64 %b) + ret i64 %0 +} From 90266f62572323e89586c5d1a00f648d6c097e06 Mon Sep 17 00:00:00 2001 From: Jim Lin Date: Mon, 7 Jul 2025 13:19:38 +0800 Subject: [PATCH 2/2] Run mem2reg pass --- .../CodeGen/RISCV/riscv-xandesperf-c-api.c | 130 +++--------------- clang/test/CodeGen/RISCV/riscv-xandesperf.c | 82 +++-------- 2 files changed, 36 insertions(+), 176 deletions(-) diff --git a/clang/test/CodeGen/RISCV/riscv-xandesperf-c-api.c b/clang/test/CodeGen/RISCV/riscv-xandesperf-c-api.c index ab872d13cc1ea..56a0dfacb80b5 100644 --- a/clang/test/CodeGen/RISCV/riscv-xandesperf-c-api.c +++ b/clang/test/CodeGen/RISCV/riscv-xandesperf-c-api.c @@ -1,44 +1,22 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // RUN: %clang_cc1 -triple riscv32 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: -disable-O0-optnone | opt -S -passes=mem2reg \ // RUN: | FileCheck %s --check-prefix=CHECK-RV32 // RUN: %clang_cc1 -triple riscv64 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: -disable-O0-optnone | opt -S -passes=mem2reg \ // RUN: | FileCheck %s --check-prefix=CHECK-RV64 #include // CHECK-RV32-LABEL: @test_ffb( // CHECK-RV32-NEXT: entry: -// CHECK-RV32-NEXT: [[A_ADDR_I:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR_I:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4 -// CHECK-RV32-NEXT: store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP4:%.*]] = call i32 @llvm.riscv.nds.ffb.i32(i32 [[TMP2]], i32 [[TMP3]]) -// CHECK-RV32-NEXT: ret i32 [[TMP4]] +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffb.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] // // CHECK-RV64-LABEL: @test_ffb( // CHECK-RV64-NEXT: entry: -// CHECK-RV64-NEXT: [[A_ADDR_I:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR_I:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[TMP0]], ptr [[A_ADDR_I]], align 8 -// CHECK-RV64-NEXT: store i64 [[TMP1]], ptr [[B_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP2:%.*]] = load i64, ptr [[A_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP3:%.*]] = load i64, ptr [[B_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP4:%.*]] = call i64 @llvm.riscv.nds.ffb.i64(i64 [[TMP2]], i64 [[TMP3]]) -// CHECK-RV64-NEXT: ret i64 [[TMP4]] +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffb.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] // long test_ffb(unsigned long a, unsigned long b) { return __riscv_nds_ffb(a, b); @@ -46,37 +24,13 @@ long test_ffb(unsigned long a, unsigned long b) { // CHECK-RV32-LABEL: @test_ffzmism( // CHECK-RV32-NEXT: entry: -// CHECK-RV32-NEXT: [[A_ADDR_I:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR_I:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4 -// CHECK-RV32-NEXT: store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP4:%.*]] = call i32 @llvm.riscv.nds.ffzmism.i32(i32 [[TMP2]], i32 [[TMP3]]) -// CHECK-RV32-NEXT: ret i32 [[TMP4]] +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffzmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] // // CHECK-RV64-LABEL: @test_ffzmism( // CHECK-RV64-NEXT: entry: -// CHECK-RV64-NEXT: [[A_ADDR_I:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR_I:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[TMP0]], ptr [[A_ADDR_I]], align 8 -// CHECK-RV64-NEXT: store i64 [[TMP1]], ptr [[B_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP2:%.*]] = load i64, ptr [[A_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP3:%.*]] = load i64, ptr [[B_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP4:%.*]] = call i64 @llvm.riscv.nds.ffzmism.i64(i64 [[TMP2]], i64 [[TMP3]]) -// CHECK-RV64-NEXT: ret i64 [[TMP4]] +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffzmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] // long test_ffzmism(unsigned long a, unsigned long b) { return __riscv_nds_ffzmism(a, b); @@ -84,37 +38,13 @@ long test_ffzmism(unsigned long a, unsigned long b) { // CHECK-RV32-LABEL: @test_ffmism( // CHECK-RV32-NEXT: entry: -// CHECK-RV32-NEXT: [[A_ADDR_I:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR_I:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4 -// CHECK-RV32-NEXT: store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP4:%.*]] = call i32 @llvm.riscv.nds.ffmism.i32(i32 [[TMP2]], i32 [[TMP3]]) -// CHECK-RV32-NEXT: ret i32 [[TMP4]] +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] // // CHECK-RV64-LABEL: @test_ffmism( // CHECK-RV64-NEXT: entry: -// CHECK-RV64-NEXT: [[A_ADDR_I:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR_I:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[TMP0]], ptr [[A_ADDR_I]], align 8 -// CHECK-RV64-NEXT: store i64 [[TMP1]], ptr [[B_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP2:%.*]] = load i64, ptr [[A_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP3:%.*]] = load i64, ptr [[B_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP4:%.*]] = call i64 @llvm.riscv.nds.ffmism.i64(i64 [[TMP2]], i64 [[TMP3]]) -// CHECK-RV64-NEXT: ret i64 [[TMP4]] +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] // long test_ffmism(unsigned long a, unsigned long b) { return __riscv_nds_ffmism(a, b); @@ -122,37 +52,13 @@ long test_ffmism(unsigned long a, unsigned long b) { // CHECK-RV32-LABEL: @test_flmism( // CHECK-RV32-NEXT: entry: -// CHECK-RV32-NEXT: [[A_ADDR_I:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR_I:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4 -// CHECK-RV32-NEXT: store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP3:%.*]] = load i32, ptr [[B_ADDR_I]], align 4 -// CHECK-RV32-NEXT: [[TMP4:%.*]] = call i32 @llvm.riscv.nds.flmism.i32(i32 [[TMP2]], i32 [[TMP3]]) -// CHECK-RV32-NEXT: ret i32 [[TMP4]] +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.flmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] // // CHECK-RV64-LABEL: @test_flmism( // CHECK-RV64-NEXT: entry: -// CHECK-RV64-NEXT: [[A_ADDR_I:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR_I:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[TMP0]], ptr [[A_ADDR_I]], align 8 -// CHECK-RV64-NEXT: store i64 [[TMP1]], ptr [[B_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP2:%.*]] = load i64, ptr [[A_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP3:%.*]] = load i64, ptr [[B_ADDR_I]], align 8 -// CHECK-RV64-NEXT: [[TMP4:%.*]] = call i64 @llvm.riscv.nds.flmism.i64(i64 [[TMP2]], i64 [[TMP3]]) -// CHECK-RV64-NEXT: ret i64 [[TMP4]] +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.flmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] // long test_flmism(unsigned long a, unsigned long b) { return __riscv_nds_flmism(a, b); diff --git a/clang/test/CodeGen/RISCV/riscv-xandesperf.c b/clang/test/CodeGen/RISCV/riscv-xandesperf.c index d4273b295ed46..4946c14709c80 100644 --- a/clang/test/CodeGen/RISCV/riscv-xandesperf.c +++ b/clang/test/CodeGen/RISCV/riscv-xandesperf.c @@ -1,30 +1,20 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // RUN: %clang_cc1 -triple riscv32 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: -disable-O0-optnone | opt -S -passes=mem2reg \ // RUN: | FileCheck %s --check-prefix=CHECK-RV32 // RUN: %clang_cc1 -triple riscv64 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: -disable-O0-optnone | opt -S -passes=mem2reg \ // RUN: | FileCheck %s --check-prefix=CHECK-RV64 // CHECK-RV32-LABEL: @test_ffb( // CHECK-RV32-NEXT: entry: -// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.nds.ffb.i32(i32 [[TMP0]], i32 [[TMP1]]) -// CHECK-RV32-NEXT: ret i32 [[TMP2]] +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffb.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] // // CHECK-RV64-LABEL: @test_ffb( // CHECK-RV64-NEXT: entry: -// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP2:%.*]] = call i64 @llvm.riscv.nds.ffb.i64(i64 [[TMP0]], i64 [[TMP1]]) -// CHECK-RV64-NEXT: ret i64 [[TMP2]] +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffb.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] // long test_ffb(unsigned long a, unsigned long b) { return __builtin_riscv_nds_ffb(a, b); @@ -32,25 +22,13 @@ long test_ffb(unsigned long a, unsigned long b) { // CHECK-RV32-LABEL: @test_ffzmism( // CHECK-RV32-NEXT: entry: -// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.nds.ffzmism.i32(i32 [[TMP0]], i32 [[TMP1]]) -// CHECK-RV32-NEXT: ret i32 [[TMP2]] +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffzmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] // // CHECK-RV64-LABEL: @test_ffzmism( // CHECK-RV64-NEXT: entry: -// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP2:%.*]] = call i64 @llvm.riscv.nds.ffzmism.i64(i64 [[TMP0]], i64 [[TMP1]]) -// CHECK-RV64-NEXT: ret i64 [[TMP2]] +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffzmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] // long test_ffzmism(unsigned long a, unsigned long b) { return __builtin_riscv_nds_ffzmism(a, b); @@ -58,25 +36,13 @@ long test_ffzmism(unsigned long a, unsigned long b) { // CHECK-RV32-LABEL: @test_ffmism( // CHECK-RV32-NEXT: entry: -// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.nds.ffmism.i32(i32 [[TMP0]], i32 [[TMP1]]) -// CHECK-RV32-NEXT: ret i32 [[TMP2]] +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] // // CHECK-RV64-LABEL: @test_ffmism( // CHECK-RV64-NEXT: entry: -// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP2:%.*]] = call i64 @llvm.riscv.nds.ffmism.i64(i64 [[TMP0]], i64 [[TMP1]]) -// CHECK-RV64-NEXT: ret i64 [[TMP2]] +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] // long test_ffmism(unsigned long a, unsigned long b) { return __builtin_riscv_nds_ffmism(a, b); @@ -84,25 +50,13 @@ long test_ffmism(unsigned long a, unsigned long b) { // CHECK-RV32-LABEL: @test_flmism( // CHECK-RV32-NEXT: entry: -// CHECK-RV32-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 -// CHECK-RV32-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4 -// CHECK-RV32-NEXT: [[TMP2:%.*]] = call i32 @llvm.riscv.nds.flmism.i32(i32 [[TMP0]], i32 [[TMP1]]) -// CHECK-RV32-NEXT: ret i32 [[TMP2]] +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.flmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] // // CHECK-RV64-LABEL: @test_flmism( // CHECK-RV64-NEXT: entry: -// CHECK-RV64-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 -// CHECK-RV64-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: store i64 [[B:%.*]], ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP1:%.*]] = load i64, ptr [[B_ADDR]], align 8 -// CHECK-RV64-NEXT: [[TMP2:%.*]] = call i64 @llvm.riscv.nds.flmism.i64(i64 [[TMP0]], i64 [[TMP1]]) -// CHECK-RV64-NEXT: ret i64 [[TMP2]] +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.flmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] // long test_flmism(unsigned long a, unsigned long b) { return __builtin_riscv_nds_flmism(a, b);