CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
214 lines
8.5 KiB
C
214 lines
8.5 KiB
C
// REQUIRES: aarch64-registered-target
|
|
|
|
// RUN: %clang_cc1_cg_arm64_neon -target-feature +fullfp16 -emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg | FileCheck %s --check-prefixes=ALL,LLVM
|
|
// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 -fclangir -emit-llvm %s -disable-O0-optnone | opt -S -passes=mem2reg,simplifycfg | FileCheck %s --check-prefixes=ALL,LLVM %}
|
|
// RUN: %if cir-enabled %{%clang_cc1_cg_arm64_neon -target-feature +fullfp16 -fclangir -emit-cir %s -disable-O0-optnone | FileCheck %s --check-prefixes=ALL,CIR %}
|
|
|
|
//=============================================================================
|
|
// NOTES
|
|
//
|
|
// Tests for unconstrained intrinsics that require the fullfp16 extension.
|
|
//
|
|
// This file contains tests that were originally located in
|
|
// * clang/test/CodeGen/AArch64/v8.2a-fp16-intrinsics.c
|
|
// The main difference is the use of RUN lines that enable ClangIR lowering;
|
|
// therefore only builtins currently supported by ClangIR are tested here.
|
|
// Once ClangIR support is complete, this file is intended to replace the
|
|
// original test file.
|
|
//
|
|
// These intrinsics expand to code containing multiple compound and declaration
|
|
// statements rather than just plain function calls, which leads to:
|
|
// * "scopes" at the CIR level, and then
|
|
// * redundant branches at the LLVM IR level.
|
|
// The default lowering path never generates those redundant LLVM IR branches,
|
|
// hence for CIR we use `opt -passes=simplifycfg` to reduce the control flow
|
|
// and to make LLVM IR match for all paths.
|
|
//
|
|
// ACLE section headings based on v2025Q2 of the ACLE specification:
|
|
// * https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#bitwise-equal-to-zero
|
|
//
|
|
// TODO: Remove `-simplifycfg` once CIR lowering includes the relevant
|
|
// optimizations to reduce the CFG.
|
|
//=============================================================================
|
|
|
|
#include <arm_fp16.h>
|
|
|
|
//===------------------------------------------------------===//
|
|
// 2.5.1.1. Addition
|
|
//===------------------------------------------------------===//
|
|
// ALL-LABEL: @test_vaddh_f16(
|
|
float16_t test_vaddh_f16(float16_t a, float16_t b) {
|
|
// CIR: {{%.*}} = cir.add {{%.*}}, {{%.*}} : !cir.f16
|
|
|
|
// LLVM-SAME: half {{.*}} [[A:%.*]], half{{.*}} [[B:%.*]]) {{.*}} {
|
|
// LLVM: [[ADD:%.*]] = fadd half [[A]], [[B]]
|
|
// LLVM: ret half [[ADD]]
|
|
return vaddh_f16(a, b);
|
|
}
|
|
|
|
//===------------------------------------------------------===//
|
|
// 2.5.10.1. Subtraction
|
|
//===------------------------------------------------------===//
|
|
// ALL-LABEL: @test_vsubh_f16(
|
|
float16_t test_vsubh_f16(float16_t a, float16_t b) {
|
|
// CIR: {{%.*}} = cir.sub {{%.*}}, {{%.*}} : !cir.f16
|
|
|
|
// LLVM-SAME: half {{.*}} [[A:%.]], half {{.*}} [[B:%.]]) {{.*}} {
|
|
// LLVM: [[SUB:%.*]] = fsub half [[A]], [[B]]
|
|
// LLVM: ret half [[SUB]]
|
|
return vsubh_f16(a, b);
|
|
}
|
|
|
|
//===------------------------------------------------------===//
|
|
// 2.5.9.1. Multiplication
|
|
//===------------------------------------------------------===//
|
|
// ALL-LABEL: @test_vmulh_f16(
|
|
float16_t test_vmulh_f16(float16_t a, float16_t b) {
|
|
// CIR: {{%.*}} = cir.mul {{%.*}}, {{%.*}} : !cir.f16
|
|
|
|
// LLVM-SAME: half {{.*}} [[A:%.]], half {{.*}} [[B:%.]]) {{.*}} {
|
|
// LLVM: [[MUL:%.*]] = fmul half [[A]], [[B]]
|
|
// LLVM: ret half [[MUL]]
|
|
return vmulh_f16(a, b);
|
|
}
|
|
|
|
//===------------------------------------------------------===//
|
|
// 2.5.1.6. Division
|
|
//===------------------------------------------------------===//
|
|
// ALL-LABEL: @test_vdivh_f16(
|
|
float16_t test_vdivh_f16(float16_t a, float16_t b) {
|
|
// CIR: {{%.*}} = cir.div {{%.*}}, {{%.*}} : !cir.f16
|
|
|
|
// LLVM-SAME: half {{.*}} [[A:%.]], half {{.*}} [[B:%.]]) {{.*}} {
|
|
// LLVM: [[DIV:%.*]] = fdiv half [[A]], [[B]]
|
|
// LLVM: ret half [[DIV]]
|
|
return vdivh_f16(a, b);
|
|
}
|
|
|
|
//===------------------------------------------------------===//
|
|
// 2.5.2.1. Bitwise equal to zero
|
|
//===------------------------------------------------------===//
|
|
// ALL-LABEL: test_vceqzh_f16
|
|
uint16_t test_vceqzh_f16(float16_t a) {
|
|
// CIR: [[C_0:%.*]] = cir.const #cir.fp<0.000000e+00>
|
|
// CIR: [[CMP:%.*]] = cir.cmp eq %{{.*}}, [[C_0]] : !cir.f16
|
|
// CIR: [[RES:%.*]] = cir.cast bool_to_int [[CMP]] : !cir.bool -> !cir.int<s, 1>
|
|
// CIR: cir.cast integral [[RES]] : !cir.int<s, 1> -> !u16i
|
|
|
|
// LLVM-SAME: (half {{.*}} [[A:%.*]])
|
|
// LLVM: [[TMP1:%.*]] = fcmp oeq half [[A]], 0.000000e+00
|
|
// LLVM: [[TMP2:%.*]] = sext i1 [[TMP1]] to i16
|
|
// LLVM: ret i16 [[TMP2]]
|
|
return vceqzh_f16(a);
|
|
}
|
|
|
|
//===------------------------------------------------------===//
|
|
// 2.5.1.1.1. Absolute value
|
|
//===------------------------------------------------------===//
|
|
// ALL-LABEL: @test_vabsh_f16
|
|
float16_t test_vabsh_f16(float16_t a) {
|
|
// CIR: {{%.*}} = cir.fabs {{%.*}} : !cir.f16
|
|
|
|
// LLVM-SAME: (half{{.*}} [[A:%.*]])
|
|
// LLVM: [[ABS:%.*]] = call half @llvm.fabs.f16(half [[A]])
|
|
// LLVM: ret half [[ABS]]
|
|
return vabsh_f16(a);
|
|
}
|
|
|
|
//===------------------------------------------------------===//
|
|
// 2.5.1.1.2. Absolute difference
|
|
//===------------------------------------------------------===//
|
|
// ALL-LABEL: test_vabdh_f16
|
|
float16_t test_vabdh_f16(float16_t a, float16_t b) {
|
|
// CIR: cir.call_llvm_intrinsic "aarch64.sisd.fabd" {{.*}} -> !cir.f16
|
|
|
|
// LLVM-SAME: half {{.*}} [[A:%.*]], half {{.*}} [[B:%.*]])
|
|
// LLVM: [[ABD:%.*]] = call half @llvm.aarch64.sisd.fabd.f16(half [[A]], half [[B]])
|
|
// LLVM: ret half [[ABD]]
|
|
return vabdh_f16(a, b);
|
|
}
|
|
|
|
//===------------------------------------------------------===//
|
|
// 2.5.1.2.1. Reciprocal estimate
|
|
//===------------------------------------------------------===//
|
|
// ALL-LABEL: test_vrecpeh_f16
|
|
float16_t test_vrecpeh_f16(float16_t a) {
|
|
// CIR: cir.call_llvm_intrinsic "aarch64.neon.frecpe" {{.*}} -> !cir.f16
|
|
|
|
// LLVM-SAME: half {{.*}} [[A:%.*]])
|
|
// LLVM: [[VREC:%.*]] = call half @llvm.aarch64.neon.frecpe.f16(half [[A]])
|
|
// LLVM: ret half [[VREC]]
|
|
return vrecpeh_f16(a);
|
|
}
|
|
|
|
// ALL-LABEL: test_vrecpxh_f16
|
|
float16_t test_vrecpxh_f16(float16_t a) {
|
|
// CIR: cir.call_llvm_intrinsic "aarch64.neon.frecpx" {{.*}} -> !cir.f16
|
|
|
|
// LLVM-SAME: half {{.*}} [[A:%.*]])
|
|
// LLVM: [[VREC:%.*]] = call half @llvm.aarch64.neon.frecpx.f16(half [[A]])
|
|
// LLVM: ret half [[VREC]]
|
|
return vrecpxh_f16(a);
|
|
}
|
|
|
|
//===------------------------------------------------------===//
|
|
// 2.5.1.2.2. Reciprocal square-root estimate
|
|
//===------------------------------------------------------===//
|
|
// ALL-LABEL: test_vrsqrteh_f16
|
|
float16_t test_vrsqrteh_f16(float16_t a) {
|
|
// CIR: cir.call_llvm_intrinsic "aarch64.neon.frsqrte" {{.*}} -> !cir.f16
|
|
|
|
// LLVM-SAME: half {{.*}} [[A:%.*]])
|
|
// LLVM: [[RND:%.*]] = call half @llvm.aarch64.neon.frsqrte.f16(half [[A]])
|
|
// LLVM: ret half [[RND]]
|
|
return vrsqrteh_f16(a);
|
|
}
|
|
|
|
// ALL-LABEL: test_vrsqrtsh_f16
|
|
float16_t test_vrsqrtsh_f16(float16_t a, float16_t b) {
|
|
// CIR: cir.call_llvm_intrinsic "aarch64.neon.frsqrts" {{.*}} -> !cir.f16
|
|
|
|
// LLVM-SAME: half {{.*}} [[A:%.*]], half {{.*}} [[B:%.*]])
|
|
// LLVM: [[RSQRTS:%.*]] = call half @llvm.aarch64.neon.frsqrts.f16(half [[A]], half [[B]])
|
|
// LLVM: ret half [[RSQRTS]]
|
|
return vrsqrtsh_f16(a, b);
|
|
}
|
|
|
|
//===------------------------------------------------------===//
|
|
// 2.5.4.1. Negate
|
|
//===------------------------------------------------------===//
|
|
// ALL-LABEL: @test_vnegh_f16
|
|
float16_t test_vnegh_f16(float16_t a) {
|
|
// CIR: cir.minus {{.*}} : !cir.f16
|
|
|
|
// LLVM-SAME: half{{.*}} [[A:%.*]])
|
|
// LLVM: [[NEG:%.*]] = fneg half [[A:%.*]]
|
|
// LLVM: ret half [[NEG]]
|
|
return vnegh_f16(a);
|
|
}
|
|
|
|
//===------------------------------------------------------===//
|
|
// 2.5.1.9.3 Fused multiply-accumulate
|
|
//===------------------------------------------------------===//
|
|
// ALL-LABEL: test_vfmah_f16
|
|
float16_t test_vfmah_f16(float16_t a, float16_t b, float16_t c) {
|
|
// CIR: cir.call_llvm_intrinsic "fma" {{.*}} : (!cir.f16, !cir.f16, !cir.f16) -> !cir.f16
|
|
|
|
// LLVM-SAME: half{{.*}} [[A:%.*]], half{{.*}} [[B:%.*]], half{{.*}} [[C:%.*]])
|
|
// LLVM: [[FMA:%.*]] = call half @llvm.fma.f16(half [[B]], half [[C]], half [[A]])
|
|
// LLVM: ret half [[FMA]]
|
|
return vfmah_f16(a, b, c);
|
|
}
|
|
|
|
// ALL-LABEL: test_vfmsh_f16
|
|
float16_t test_vfmsh_f16(float16_t a, float16_t b, float16_t c) {
|
|
// CIR: [[SUB:%.*]] = cir.minus %{{.*}} : !cir.f16
|
|
// CIR: cir.call_llvm_intrinsic "fma" [[SUB]], {{.*}} : (!cir.f16, !cir.f16, !cir.f16) -> !cir.f16
|
|
|
|
// LLVM-SAME: half{{.*}} [[A:%.*]], half{{.*}} [[B:%.*]], half{{.*}} [[C:%.*]])
|
|
// LLVM: [[SUB:%.*]] = fneg half [[B]]
|
|
// LLVM: [[ADD:%.*]] = call half @llvm.fma.f16(half [[SUB]], half [[C]], half [[A]])
|
|
// LLVM: ret half [[ADD]]
|
|
return vfmsh_f16(a, b, c);
|
|
}
|