[PATCH] D42962: [ARM] Allow 64- and 128-bit types with 't' inline asm constraint

Pablo Barrio via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 6 06:46:06 PST 2018


pbarrio created this revision.
pbarrio added reviewers: grosbach, rengolin.
Herald added subscribers: kristof.beyls, eraman, javed.absar, aemerson.

In LLVM, 't' selects a floating-point/SIMD register and only supports
32-bit values. This is appropriately documented in the LLVM Language
Reference Manual. However, this behaviour diverges from that of GCC, where
't' selects the lower Q registers Q0-Q8 and its DX and SX variants
depending on an additional operand modifier (q/e/f).

For example, the following C code:

#include <arm_neon.h>
float32x4_t a, b, x;
asm("vadd.f32 %0, %1, %2" : "=t" (x) : "t" (a), "t" (b))

results in the following assembly if compiled with GCC:

vadd.f32 s0, s0, s1

whereas LLVM will show "error: couldn't allocate output register for
constraint 't'", since a, b, x are 128-bit variables, not 32-bit.

This patch extends the use of 't' to mean that of GCC, thus allowing
selection of the lower Q vector regs and their D/S variants. For example,
the earlier code will now compile as:

vadd.f32 q0, q0, q1

This behaviour still differs from that of GCC but I think it is actually
more correct, since LLVM picks up the right register type based on the
datatype of x, while GCC would need an extra operand modifier to achieve
the same result, as follows:

asm("vadd.f32 %q0, %q1, %q2" : "=t" (x) : "t" (a), "t" (b))

Since this is only an extension of functionality, existing code should not
be affected by this change.


Repository:
  rL LLVM

https://reviews.llvm.org/D42962

Files:
  docs/LangRef.rst
  lib/Target/ARM/ARMISelLowering.cpp
  test/CodeGen/ARM/inlineasm-errors.ll
  test/CodeGen/ARM/inlineasm.ll


Index: test/CodeGen/ARM/inlineasm.ll
===================================================================
--- test/CodeGen/ARM/inlineasm.ll
+++ test/CodeGen/ARM/inlineasm.ll
@@ -16,3 +16,19 @@
 	%ret = call float asm "vcvt.f32.s32 $0, $1\0A", "=t,t"(i32 %i)
 	ret float %ret
 }
+
+define <2 x float> @t-constraint-float-vectors-64bit(<2 x float> %a, <2 x float> %b) {
+entry:
+	; CHECK-LABEL: t-constraint-float-vectors-64bit
+	; CHECK: vadd.f32 d{{[0-7]}}, d{{[0-7]}}, d{{[0-7]}}
+	%0 = tail call <2 x float> asm "vadd.F32 $0, $1, $2", "=t,t,t"(<2 x float> %a, <2 x float> %b)
+	ret <2 x float> %0
+}
+
+define <4 x float> @t-constraint-float-vectors-128bit(<4 x float> %a, <4 x float> %b) {
+entry:
+	; CHECK-LABEL: t-constraint-float-vectors-128bit
+	; CHECK: vadd.f32 q{{[0-7]}}, q{{[0-7]}}, q{{[0-7]}}
+	%0 = tail call <4 x float> asm "vadd.F32 $0, $1, $2", "=t,t,t"(<4 x float> %a, <4 x float> %b)
+	ret <4 x float> %0
+}
Index: test/CodeGen/ARM/inlineasm-errors.ll
===================================================================
--- /dev/null
+++ test/CodeGen/ARM/inlineasm-errors.ll
@@ -0,0 +1,9 @@
+; RUN: not llc -mtriple=armv8-eabi -mattr=+neon %s -o /dev/null 2<&1 | FileCheck %s
+
+; CHECK: inline assembly requires more registers than available
+define <4 x float> @t-constraint-float-vectors-too-few-regs(<4 x float> %a, <4 x float> %b) {
+entry:
+	%0 = tail call { <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float> } asm "vadd.F32 $0, $9, $10\0A\09vadd.F32 $1, $9, $10\0A\09vadd.F32 $2, $9, $10\0A\09vadd.F32 $3, $9, $10\0A\09vadd.F32 $4, $9, $10\0A\09vadd.F32 $5, $9, $10\0A\09vadd.F32 $6, $9, $10\0A\09vadd.F32 $7, $9, $10\0A\09vadd.F32 $8, $9, $10", "=t,=t,=t,=t,=t,=t,=t,=t,=t,=t,t,t"(<4 x float> %a, <4 x float> %b)
+	%asmresult = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float>, <4 x float> } %0, 0
+	ret <4 x float> %asmresult
+}
Index: lib/Target/ARM/ARMISelLowering.cpp
===================================================================
--- lib/Target/ARM/ARMISelLowering.cpp
+++ lib/Target/ARM/ARMISelLowering.cpp
@@ -13467,8 +13467,14 @@
         return RCPair(0U, &ARM::QPR_8RegClass);
       break;
     case 't':
+      if (VT == MVT::Other)
+        break;
       if (VT == MVT::f32 || VT == MVT::i32)
         return RCPair(0U, &ARM::SPRRegClass);
+      if (VT.getSizeInBits() == 64)
+        return RCPair(0U, &ARM::DPR_VFP2RegClass);
+      if (VT.getSizeInBits() == 128)
+        return RCPair(0U, &ARM::QPR_VFP2RegClass);
       break;
     }
   }
Index: docs/LangRef.rst
===================================================================
--- docs/LangRef.rst
+++ docs/LangRef.rst
@@ -3652,8 +3652,8 @@
   ``d0-d31``, or ``q0-q15``.
 - ``x``: A 32, 64, or 128-bit floating-point/SIMD register: ``s0-s15``,
   ``d0-d7``, or ``q0-q3``.
-- ``t``: A floating-point/SIMD register, only supports 32-bit values:
-  ``s0-s31``.
+- ``t``: A low floating-point/SIMD register: ``s0-s31``, ``d0-d16``, or
+  ``q0-q8``.
 
 ARM's Thumb1 mode:
 
@@ -3672,8 +3672,8 @@
   ``d0-d31``, or ``q0-q15``.
 - ``x``: A 32, 64, or 128-bit floating-point/SIMD register: ``s0-s15``,
   ``d0-d7``, or ``q0-q3``.
-- ``t``: A floating-point/SIMD register, only supports 32-bit values:
-  ``s0-s31``.
+- ``t``: A low floating-point/SIMD register: ``s0-s31``, ``d0-d16``, or
+  ``q0-q8``.
 
 
 Hexagon:


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D42962.132991.patch
Type: text/x-patch
Size: 3475 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180206/4c1bd59d/attachment.bin>


More information about the llvm-commits mailing list