diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -181,13 +181,16 @@ Arm and AArch64 Support in Clang -------------------------------- -* The hard-float ABI is now available in Armv8.1-M configurations that +- The hard-float ABI is now available in Armv8.1-M configurations that have integer MVE instructions (and therefore have FP registers) but no scalar or vector floating point computation. Previously, trying to select the hard-float ABI on such a target (via ``-mfloat-abi=hard`` or a triple ending in ``hf``) would silently use the soft-float ABI instead. +- Clang builtin ``__arithmetic_fence`` and the command line option ``-fprotect-parens`` + are now enabled for AArch64. + Floating Point Support in Clang ------------------------------- - Add ``__builtin_elementwise_log`` builtin for floating point types only. diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h --- a/clang/lib/Basic/Targets/AArch64.h +++ b/clang/lib/Basic/Targets/AArch64.h @@ -155,6 +155,8 @@ ParsedTargetAttr parseTargetAttr(StringRef Str) const override; bool supportsTargetAttributeTune() const override { return true; } + bool checkArithmeticFenceSupported() const override { return true; } + bool hasBFloat16Type() const override; CallingConvCheckResult checkCallingConvention(CallingConv CC) const override; diff --git a/clang/test/AST/arithmetic-fence-builtin.c b/clang/test/AST/arithmetic-fence-builtin.c --- a/clang/test/AST/arithmetic-fence-builtin.c +++ b/clang/test/AST/arithmetic-fence-builtin.c @@ -2,30 +2,54 @@ // RUN: %clang_cc1 -ast-dump -triple i386-pc-linux-gnu %s \ // RUN: | FileCheck %s --strict-whitespace --check-prefixes=CHECK,CHECK1 // +// RUN: %clang_cc1 -ast-dump -triple aarch64-unknown-linux-gnu %s \ +// RUN: | FileCheck %s --strict-whitespace --check-prefixes=CHECK,CHECK1 +// // RUN: %clang_cc1 -ast-dump -triple i386-pc-linux-gnu -DFAST -mreassociate %s \ // RUN: | FileCheck %s --strict-whitespace --check-prefixes=CHECK,CHECK1 // +// RUN: %clang_cc1 -ast-dump -triple aarch64-unknown-linux-gnu -DFAST -mreassociate %s \ +// RUN: | FileCheck %s --strict-whitespace --check-prefixes=CHECK,CHECK1 +// // RUN: %clang_cc1 -ast-dump -triple i386-pc-linux-gnu -DFAST -mreassociate %s \ // RUN: -fprotect-parens \ // RUN: | FileCheck %s --strict-whitespace --check-prefixes=CHECK,CHECK2 // +// RUN: %clang_cc1 -ast-dump -triple aarch64-unknown-linux-gnu -DFAST -mreassociate %s \ +// RUN: -fprotect-parens \ +// RUN: | FileCheck %s --strict-whitespace --check-prefixes=CHECK,CHECK2 +// // Tests with serialization: // RUN: %clang_cc1 -ast-dump -triple i386-pc-linux-gnu -emit-pch -o %t %s // RUN: %clang_cc1 -triple i386-pc-linux-gnu -include-pch %t -ast-dump-all /dev/null \ // RUN: | FileCheck %s --strict-whitespace // +// RUN: %clang_cc1 -ast-dump -triple aarch64-unknown-linux-gnu -emit-pch -o %t %s +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -include-pch %t -ast-dump-all /dev/null \ +// RUN: | FileCheck %s --strict-whitespace +// // RUN: %clang_cc1 -ast-dump -triple i386-pc-linux-gnu -DFAST -mreassociate %s \ // RUN: -emit-pch -o %t // RUN: %clang_cc1 -triple i386-pc-linux-gnu -include-pch %t -ast-dump-all /dev/null \ // RUN: | FileCheck %s --strict-whitespace --check-prefixes=CHECK,CHECK1 // +// RUN: %clang_cc1 -ast-dump -triple aarch64-unknown-linux-gnu -DFAST -mreassociate %s \ +// RUN: -emit-pch -o %t +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -include-pch %t -ast-dump-all /dev/null \ +// RUN: | FileCheck %s --strict-whitespace --check-prefixes=CHECK,CHECK1 +// // RUN: %clang_cc1 -ast-dump -triple i386-pc-linux-gnu -DFAST -mreassociate %s \ // RUN: -fprotect-parens \ // RUN: -emit-pch -o %t // RUN: %clang_cc1 -triple i386-pc-linux-gnu -include-pch %t -ast-dump-all /dev/null -fprotect-parens\ // RUN: | FileCheck %s --strict-whitespace --check-prefixes=CHECK,CHECK2 - // +// RUN: %clang_cc1 -ast-dump -triple aarch64-unknown-linux-gnu -DFAST -mreassociate %s \ +// RUN: -fprotect-parens \ +// RUN: -emit-pch -o %t +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -include-pch %t -ast-dump-all /dev/null -fprotect-parens\ +// RUN: | FileCheck %s --strict-whitespace --check-prefixes=CHECK,CHECK2 + int v; int addit(float a, float b) { diff --git a/clang/test/CodeGen/arithmetic-fence-builtin.c b/clang/test/CodeGen/arithmetic-fence-builtin.c --- a/clang/test/CodeGen/arithmetic-fence-builtin.c +++ b/clang/test/CodeGen/arithmetic-fence-builtin.c @@ -3,15 +3,26 @@ // RUN: -mreassociate \ // RUN: -o - %s | FileCheck --check-prefixes CHECK,CHECKFAST,CHECKNP %s // +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -emit-llvm -DFAST \ +// RUN: -mreassociate \ +// RUN: -o - %s | FileCheck --check-prefixes CHECK,CHECKFAST,CHECKNP %s +// // Test with fast math and fprotect-parens // RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -DFAST \ // RUN: -mreassociate -fprotect-parens -ffp-contract=on\ // RUN: -o - %s | FileCheck --check-prefixes CHECK,CHECKFAST,CHECKPP %s // +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -emit-llvm -DFAST \ +// RUN: -mreassociate -fprotect-parens -ffp-contract=on\ +// RUN: -o - %s | FileCheck --check-prefixes CHECK,CHECKFAST,CHECKPP %s +// // Test without fast math: llvm intrinsic not created // RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -fprotect-parens\ // RUN: -o - %s | FileCheck --implicit-check-not="llvm.arithmetic.fence" %s // +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -emit-llvm -fprotect-parens\ +// RUN: -o - %s | FileCheck --implicit-check-not="llvm.arithmetic.fence" %s +// // Test with fast math on spir target // RUN: %clang_cc1 -triple spir64 -emit-llvm -DFAST \ // RUN: -mreassociate -o - %s \ diff --git a/llvm/test/CodeGen/AArch64/arithmetic_fence.ll b/llvm/test/CodeGen/AArch64/arithmetic_fence.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/arithmetic_fence.ll @@ -0,0 +1,129 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=-neon -fp-contract=fast | FileCheck %s --check-prefix=Aarch64 +; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+neon -fp-contract=fast | FileCheck %s --check-prefix=Aarch64-Neon + +define float @f1(float %a, float %b, float %c) { +; Aarch64-LABEL: f1: +; Aarch64: // %bb.0: +; Aarch64-NEXT: fmadd s0, s1, s0, s2 +; Aarch64-NEXT: ret +; +; Aarch64-Neon-LABEL: f1: +; Aarch64-Neon: // %bb.0: +; Aarch64-Neon-NEXT: fmadd s0, s1, s0, s2 +; Aarch64-Neon-NEXT: ret + %mul = fmul fast float %b, %a + %add = fadd fast float %mul, %c + ret float %add +} + +define float @f2(float %a, float %b, float %c) { +; Aarch64-LABEL: f2: +; Aarch64: // %bb.0: +; Aarch64-NEXT: fmul s0, s1, s0 +; Aarch64-NEXT: //ARITH_FENCE +; Aarch64-NEXT: fadd s0, s0, s2 +; Aarch64-NEXT: ret +; +; Aarch64-Neon-LABEL: f2: +; Aarch64-Neon: // %bb.0: +; Aarch64-Neon-NEXT: fmul s0, s1, s0 +; Aarch64-Neon-NEXT: //ARITH_FENCE +; Aarch64-Neon-NEXT: fadd s0, s0, s2 +; Aarch64-Neon-NEXT: ret + %mul = fmul fast float %b, %a + %tmp = call float @llvm.arithmetic.fence.f32(float %mul) + %add = fadd fast float %tmp, %c + ret float %add +} + +define double @f3(double %a) { +; Aarch64-LABEL: f3: +; Aarch64: // %bb.0: +; Aarch64-NEXT: fmov d1, #4.00000000 +; Aarch64-NEXT: fmul d0, d0, d1 +; Aarch64-NEXT: ret +; +; Aarch64-Neon-LABEL: f3: +; Aarch64-Neon: // %bb.0: +; Aarch64-Neon-NEXT: fmov d1, #4.00000000 +; Aarch64-Neon-NEXT: fmul d0, d0, d1 +; Aarch64-Neon-NEXT: ret + %1 = fadd fast double %a, %a + %2 = fadd fast double %a, %a + %3 = fadd fast double %1, %2 + ret double %3 +} + +define double @f4(double %a) { +; Aarch64-LABEL: f4: +; Aarch64: // %bb.0: +; Aarch64-NEXT: fadd d0, d0, d0 +; Aarch64-NEXT: fmov d1, d0 +; Aarch64-NEXT: //ARITH_FENCE +; Aarch64-NEXT: fadd d0, d1, d0 +; Aarch64-NEXT: ret +; +; Aarch64-Neon-LABEL: f4: +; Aarch64-Neon: // %bb.0: +; Aarch64-Neon-NEXT: fadd d0, d0, d0 +; Aarch64-Neon-NEXT: fmov d1, d0 +; Aarch64-Neon-NEXT: //ARITH_FENCE +; Aarch64-Neon-NEXT: fadd d0, d1, d0 +; Aarch64-Neon-NEXT: ret + %1 = fadd fast double %a, %a + %t = call double @llvm.arithmetic.fence.f64(double %1) + %2 = fadd fast double %a, %a + %3 = fadd fast double %t, %2 + ret double %3 +} + +define <2 x float> @f5(<2 x float> %a) { +; Aarch64-LABEL: f5: +; Aarch64: // %bb.0: +; Aarch64-NEXT: fmov s2, #4.00000000 +; Aarch64-NEXT: fmul s0, s0, s2 +; Aarch64-NEXT: fmul s1, s1, s2 +; Aarch64-NEXT: ret +; +; Aarch64-Neon-LABEL: f5: +; Aarch64-Neon: // %bb.0: +; Aarch64-Neon-NEXT: fmov v1.2s, #4.00000000 +; Aarch64-Neon-NEXT: fmul v0.2s, v0.2s, v1.2s +; Aarch64-Neon-NEXT: ret + %1 = fadd fast <2 x float> %a, %a + %2 = fadd fast <2 x float> %a, %a + %3 = fadd fast <2 x float> %1, %2 + ret <2 x float> %3 +} + +define <2 x float> @f6(<2 x float> %a) { +; Aarch64-LABEL: f6: +; Aarch64: // %bb.0: +; Aarch64-NEXT: fadd s0, s0, s0 +; Aarch64-NEXT: fadd s1, s1, s1 +; Aarch64-NEXT: fmov s2, s1 +; Aarch64-NEXT: fmov s3, s0 +; Aarch64-NEXT: //ARITH_FENCE +; Aarch64-NEXT: //ARITH_FENCE +; Aarch64-NEXT: fadd s0, s3, s0 +; Aarch64-NEXT: fadd s1, s2, s1 +; Aarch64-NEXT: ret +; +; Aarch64-Neon-LABEL: f6: +; Aarch64-Neon: // %bb.0: +; Aarch64-Neon-NEXT: fadd v0.2s, v0.2s, v0.2s +; Aarch64-Neon-NEXT: fmov d1, d0 +; Aarch64-Neon-NEXT: //ARITH_FENCE +; Aarch64-Neon-NEXT: fadd v0.2s, v1.2s, v0.2s +; Aarch64-Neon-NEXT: ret + %1 = fadd fast <2 x float> %a, %a + %t = call <2 x float> @llvm.arithmetic.fence.v2f32(<2 x float> %1) + %2 = fadd fast <2 x float> %a, %a + %3 = fadd fast <2 x float> %t, %2 + ret <2 x float> %3 +} + +declare float @llvm.arithmetic.fence.f32(float) +declare double @llvm.arithmetic.fence.f64(double) +declare <2 x float> @llvm.arithmetic.fence.v2f32(<2 x float>)