]> granicus.if.org Git - clang/commitdiff
[ARM] Allow passing/returning of __fp16 arguments
authorOliver Stannard <oliver.stannard@arm.com>
Thu, 3 Sep 2015 12:40:58 +0000 (12:40 +0000)
committerOliver Stannard <oliver.stannard@arm.com>
Thu, 3 Sep 2015 12:40:58 +0000 (12:40 +0000)
The ACLE (ARM C Language Extensions) 2.0 allows the __fp16 type to be
used as a functon argument or return type (ACLE 1.1 did not).

The current public release of the AAPCS (2.09) states that __fp16 values
should be converted to single-precision before being passed or returned,
but AAPCS 2.10 (to be released shortly) changes this, so that they are
passed in the least-significant 16 bits of either a GPR (for base AAPCS)
or a single-precision register (for AAPCS-VFP). This does not change how
arguments are passed if they get passed on the stack.

This patch brings clang up to compliance with the latest versions of
both of these specs.

We can now set the __ARM_FP16_ARGS ACLE predefine, and we have always
been able to set the __ARM_FP16_FORMAT_IEEE predefine (we do not support
the alternative format).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@246764 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Basic/Targets.cpp
lib/CodeGen/TargetInfo.cpp
lib/Driver/Tools.cpp
test/CodeGen/arm-fp16-arguments.c [new file with mode: 0644]
test/Preprocessor/arm-acle-6.5.c
test/Preprocessor/arm-target-features.c

index 77cce95dca27ee55f1638a2552d67c77b185e66e..bc204b6b3ba28fbe561d02cb271031695a7a15ce 100644 (file)
@@ -4568,6 +4568,10 @@ public:
     // ACLE predefines.
     Builder.defineMacro("__ARM_ACLE", "200");
 
+    // FP16 support (we currently only support IEEE format).
+    Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
+    Builder.defineMacro("__ARM_FP16_ARGS", "1");
+
     // Subtarget options.
 
     // FIXME: It's more complicated than this and we don't really support
index e97b33a54e894b7bd9a8d5a2490ecacb99b350a7..f1b8b03eb60a9fc97e6f7b99439f74af5d50e829 100644 (file)
@@ -4714,6 +4714,16 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty,
     return ABIArgInfo::getIndirect(0, /*ByVal=*/false);
   }
 
+  // __fp16 gets passed as if it were an int or float, but with the top 16 bits
+  // unspecified. This is not done for OpenCL as it handles the half type
+  // natively, and does not need to interwork with AAPCS code.
+  if (Ty->isHalfType() && !getContext().getLangOpts().OpenCL) {
+    llvm::Type *ResType = IsEffectivelyAAPCS_VFP ?
+      llvm::Type::getFloatTy(getVMContext()) :
+      llvm::Type::getInt32Ty(getVMContext());
+    return ABIArgInfo::getDirect(ResType);
+  }
+
   if (!isAggregateTypeForABI(Ty)) {
     // Treat an enum type as its underlying type.
     if (const EnumType *EnumTy = Ty->getAs<EnumType>()) {
@@ -4872,6 +4882,16 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy,
     return ABIArgInfo::getIndirect(0);
   }
 
+  // __fp16 gets returned as if it were an int or float, but with the top 16
+  // bits unspecified. This is not done for OpenCL as it handles the half type
+  // natively, and does not need to interwork with AAPCS code.
+  if (RetTy->isHalfType() && !getContext().getLangOpts().OpenCL) {
+    llvm::Type *ResType = IsEffectivelyAAPCS_VFP ?
+      llvm::Type::getFloatTy(getVMContext()) :
+      llvm::Type::getInt32Ty(getVMContext());
+    return ABIArgInfo::getDirect(ResType);
+  }
+
   if (!isAggregateTypeForABI(RetTy)) {
     // Treat an enum type as its underlying type.
     if (const EnumType *EnumTy = RetTy->getAs<EnumType>())
index 75bf7e40417be0f7350d7c05a00c386409629d98..8afab2f23b0c00f5a0966138045c3079ba751395 100644 (file)
@@ -4293,9 +4293,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back("-mstack-probe-size=0");
   }
 
-  if (getToolChain().getArch() == llvm::Triple::aarch64 ||
-      getToolChain().getArch() == llvm::Triple::aarch64_be)
+  switch (getToolChain().getArch()) {
+  case llvm::Triple::aarch64:
+  case llvm::Triple::aarch64_be:
+  case llvm::Triple::arm:
+  case llvm::Triple::armeb:
+  case llvm::Triple::thumb:
+  case llvm::Triple::thumbeb:
     CmdArgs.push_back("-fallow-half-arguments-and-returns");
+    break;
+
+  default:
+    break;
+  }
 
   if (Arg *A = Args.getLastArg(options::OPT_mrestrict_it,
                                options::OPT_mno_restrict_it)) {
diff --git a/test/CodeGen/arm-fp16-arguments.c b/test/CodeGen/arm-fp16-arguments.c
new file mode 100644 (file)
index 0000000..15a9ceb
--- /dev/null
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple armv7a--none-eabi -target-abi aapcs -mfloat-abi soft -fallow-half-arguments-and-returns -emit-llvm -o - -O1 %s | FileCheck %s --check-prefix=CHECK --check-prefix=SOFT
+// RUN: %clang_cc1 -triple armv7a--none-eabi -target-abi aapcs -mfloat-abi hard -fallow-half-arguments-and-returns -emit-llvm -o - -O1 %s | FileCheck %s --check-prefix=CHECK --check-prefix=HARD
+
+__fp16 g;
+
+void t1(__fp16 a) { g = a; }
+// SOFT: define void @t1(i32 [[PARAM:%.*]])
+// SOFT: [[TRUNC:%.*]] = trunc i32 [[PARAM]] to i16
+// HARD: define arm_aapcs_vfpcc void @t1(float [[PARAM:%.*]])
+// HARD: [[BITCAST:%.*]] = bitcast float [[PARAM]] to i32
+// HARD: [[TRUNC:%.*]] = trunc i32 [[BITCAST]] to i16
+// CHECK: store i16 [[TRUNC]], i16* bitcast (half* @g to i16*)
+
+__fp16 t2() { return g; }
+// SOFT: define i32 @t2()
+// HARD: define arm_aapcs_vfpcc float @t2()
+// CHECK: [[LOAD:%.*]] = load i16, i16* bitcast (half* @g to i16*)
+// CHECK: [[ZEXT:%.*]] = zext i16 [[LOAD]] to i32
+// SOFT: ret i32 [[ZEXT]]
+// HARD: [[BITCAST:%.*]] = bitcast i32 [[ZEXT]] to float
+// HARD: ret float [[BITCAST]]
index 9db83b774b0c6746967c42b69d5614ff91a54a64..bb3b25d50694fd446a876b969749d6843f9b8217 100644 (file)
@@ -1,6 +1,6 @@
 // RUN: %clang -target arm-eabi -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-DEFAULT
 
-// CHECK-DEFAULT-NOT: __ARM_FP
+// CHECK-DEFAULT-NOT: __ARM_FP 0x
 
 // RUN: %clang -target arm-eabi -mfpu=vfp -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-SP-DP
 // RUN: %clang -target arm-eabi -mfpu=vfp3 -x c -E -dM %s -o - | FileCheck %s -check-prefix CHECK-SP-DP
index c4b887f4552605124a8a78c5262f547cc6e395a1..0cc909444fc45259c5408ee5379c22c1481cdd6d 100644 (file)
@@ -5,6 +5,8 @@
 // CHECK: __ARM_FEATURE_CRC32 1
 // CHECK: __ARM_FEATURE_DIRECTED_ROUNDING 1
 // CHECK: __ARM_FEATURE_NUMERIC_MAXMIN 1
+// CHECK: __ARM_FP16_ARGS 1
+// CHECK: __ARM_FP16_FORMAT_IEEE 1
 
 // RUN: %clang -target armv7a-none-linux-gnu -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-V7 %s
 // CHECK-V7: __ARMEL__ 1