[PATCH] D78756: [SveEmitter] Add builtins for svreinterpret

2020-05-05 Thread Sander de Smalen via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG5ba329059f9c: [SveEmitter] Add builtins for svreinterpret 
(authored by sdesmalen).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78756/new/

https://reviews.llvm.org/D78756

Files:
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret.c
  clang/test/CodeGen/aarch64-sve-intrinsics/negative/big_endian.c
  clang/utils/TableGen/SveEmitter.cpp

Index: clang/utils/TableGen/SveEmitter.cpp
===
--- clang/utils/TableGen/SveEmitter.cpp
+++ clang/utils/TableGen/SveEmitter.cpp
@@ -237,6 +237,23 @@
 
 class SVEEmitter {
 private:
+  // The reinterpret builtins are generated separately because they
+  // need the cross product of all types (121 functions in total),
+  // which is inconvenient to specify in the arm_sve.td file or
+  // generate in CGBuiltin.cpp.
+  struct ReinterpretTypeInfo {
+const char *Suffix;
+const char *Type;
+const char *BuiltinType;
+  };
+  SmallVector Reinterprets = {
+  {"s8", "svint8_t", "q16Sc"},   {"s16", "svint16_t", "q8Ss"},
+  {"s32", "svint32_t", "q4Si"},  {"s64", "svint64_t", "q2SWi"},
+  {"u8", "svuint8_t", "q16Uc"},  {"u16", "svuint16_t", "q8Us"},
+  {"u32", "svuint32_t", "q4Ui"}, {"u64", "svuint64_t", "q2UWi"},
+  {"f16", "svfloat16_t", "q8h"}, {"f32", "svfloat32_t", "q4f"},
+  {"f64", "svfloat64_t", "q2d"}};
+
   RecordKeeper 
   llvm::StringMap EltTypes;
   llvm::StringMap MemEltTypes;
@@ -1008,6 +1025,10 @@
   OS << "#error \"SVE support not enabled\"\n";
   OS << "#else\n\n";
 
+  OS << "#if !defined(__LITTLE_ENDIAN__)\n";
+  OS << "#error \"Big endian is currently not supported for arm_sve.h\"\n";
+  OS << "#endif\n";
+
   OS << "#include \n\n";
   OS << "#ifdef  __cplusplus\n";
   OS << "extern \"C\" {\n";
@@ -1074,6 +1095,22 @@
   OS << "#define __aio static inline __attribute__((__always_inline__, "
 "__nodebug__, __overloadable__))\n\n";
 
+  // Add reinterpret functions.
+  for (auto ShortForm : { false, true } )
+for (const ReinterpretTypeInfo  : Reinterprets)
+  for (const ReinterpretTypeInfo  : Reinterprets) {
+if (ShortForm) {
+  OS << "__aio " << From.Type << " svreinterpret_" << From.Suffix;
+  OS << "(" << To.Type << " op) {\n";
+  OS << "  return __builtin_sve_reinterpret_" << From.Suffix << "_"
+ << To.Suffix << "(op);\n";
+  OS << "}\n\n";
+} else
+  OS << "#define svreinterpret_" << From.Suffix << "_" << To.Suffix
+ << "(...) __builtin_sve_reinterpret_" << From.Suffix << "_"
+ << To.Suffix << "(__VA_ARGS__)\n";
+  }
+
   SmallVector, 128> Defs;
   std::vector RV = Records.getAllDerivedDefinitions("Inst");
   for (auto *R : RV)
@@ -1148,8 +1185,16 @@
   OS << "BUILTIN(__builtin_sve_" << Def->getMangledName() << ", \""
  << Def->getBuiltinTypeStr() << "\", \"n\")\n";
   }
+
+  // Add reinterpret builtins
+  for (const ReinterpretTypeInfo  : Reinterprets)
+for (const ReinterpretTypeInfo  : Reinterprets)
+  OS << "BUILTIN(__builtin_sve_reinterpret_" << From.Suffix << "_"
+ << To.Suffix << +", \"" << From.BuiltinType << To.BuiltinType
+ << "\", \"n\")\n";
+
   OS << "#endif\n\n";
-}
+  }
 
 void SVEEmitter::createCodeGenMap(raw_ostream ) {
   std::vector RV = Records.getAllDerivedDefinitions("Inst");
Index: clang/test/CodeGen/aarch64-sve-intrinsics/negative/big_endian.c
===
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/negative/big_endian.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64_be-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+
+// expected-error@* {{Big endian is currently not supported for arm_sve.h}}
+#include 
Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret.c
===
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret.c
@@ -0,0 +1,960 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+
+#include 
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+svint8_t test_svreinterpret_s8_s8(svint8_t op)
+{
+  // CHECK-LABEL: test_svreinterpret_s8_s8
+  // CHECK: ret 

[PATCH] D78756: [SveEmitter] Add builtins for svreinterpret

2020-05-04 Thread Eli Friedman via Phabricator via cfe-commits
efriedma accepted this revision.
efriedma added a comment.
This revision is now accepted and ready to land.

LGTM


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78756/new/

https://reviews.llvm.org/D78756



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D78756: [SveEmitter] Add builtins for svreinterpret

2020-05-04 Thread Sander de Smalen via Phabricator via cfe-commits
sdesmalen updated this revision to Diff 261892.
sdesmalen added a comment.

- Added FIXME in CGBuiltins for big-endian svreinterpret.
- Added diagnostic in arm_sve.h that big-endian is not yet supported.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78756/new/

https://reviews.llvm.org/D78756

Files:
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret.c
  clang/test/CodeGen/aarch64-sve-intrinsics/negative/big_endian.c
  clang/utils/TableGen/SveEmitter.cpp

Index: clang/utils/TableGen/SveEmitter.cpp
===
--- clang/utils/TableGen/SveEmitter.cpp
+++ clang/utils/TableGen/SveEmitter.cpp
@@ -237,6 +237,23 @@
 
 class SVEEmitter {
 private:
+  // The reinterpret builtins are generated separately because they
+  // need the cross product of all types (121 functions in total),
+  // which is inconvenient to specify in the arm_sve.td file or
+  // generate in CGBuiltin.cpp.
+  struct ReinterpretTypeInfo {
+const char *Suffix;
+const char *Type;
+const char *BuiltinType;
+  };
+  SmallVector Reinterprets = {
+  {"s8", "svint8_t", "q16Sc"},   {"s16", "svint16_t", "q8Ss"},
+  {"s32", "svint32_t", "q4Si"},  {"s64", "svint64_t", "q2SWi"},
+  {"u8", "svuint8_t", "q16Uc"},  {"u16", "svuint16_t", "q8Us"},
+  {"u32", "svuint32_t", "q4Ui"}, {"u64", "svuint64_t", "q2UWi"},
+  {"f16", "svfloat16_t", "q8h"}, {"f32", "svfloat32_t", "q4f"},
+  {"f64", "svfloat64_t", "q2d"}};
+
   RecordKeeper 
   llvm::StringMap EltTypes;
   llvm::StringMap MemEltTypes;
@@ -1008,6 +1025,10 @@
   OS << "#error \"SVE support not enabled\"\n";
   OS << "#else\n\n";
 
+  OS << "#if !defined(__LITTLE_ENDIAN__)\n";
+  OS << "#error \"Big endian is currently not supported for arm_sve.h\"\n";
+  OS << "#endif\n";
+
   OS << "#include \n\n";
   OS << "#ifdef  __cplusplus\n";
   OS << "extern \"C\" {\n";
@@ -1074,6 +1095,22 @@
   OS << "#define __aio static inline __attribute__((__always_inline__, "
 "__nodebug__, __overloadable__))\n\n";
 
+  // Add reinterpret functions.
+  for (auto ShortForm : { false, true } )
+for (const ReinterpretTypeInfo  : Reinterprets)
+  for (const ReinterpretTypeInfo  : Reinterprets) {
+if (ShortForm) {
+  OS << "__aio " << From.Type << " svreinterpret_" << From.Suffix;
+  OS << "(" << To.Type << " op) {\n";
+  OS << "  return __builtin_sve_reinterpret_" << From.Suffix << "_"
+ << To.Suffix << "(op);\n";
+  OS << "}\n\n";
+} else
+  OS << "#define svreinterpret_" << From.Suffix << "_" << To.Suffix
+ << "(...) __builtin_sve_reinterpret_" << From.Suffix << "_"
+ << To.Suffix << "(__VA_ARGS__)\n";
+  }
+
   SmallVector, 128> Defs;
   std::vector RV = Records.getAllDerivedDefinitions("Inst");
   for (auto *R : RV)
@@ -1148,8 +1185,16 @@
   OS << "BUILTIN(__builtin_sve_" << Def->getMangledName() << ", \""
  << Def->getBuiltinTypeStr() << "\", \"n\")\n";
   }
+
+  // Add reinterpret builtins
+  for (const ReinterpretTypeInfo  : Reinterprets)
+for (const ReinterpretTypeInfo  : Reinterprets)
+  OS << "BUILTIN(__builtin_sve_reinterpret_" << From.Suffix << "_"
+ << To.Suffix << +", \"" << From.BuiltinType << To.BuiltinType
+ << "\", \"n\")\n";
+
   OS << "#endif\n\n";
-}
+  }
 
 void SVEEmitter::createCodeGenMap(raw_ostream ) {
   std::vector RV = Records.getAllDerivedDefinitions("Inst");
Index: clang/test/CodeGen/aarch64-sve-intrinsics/negative/big_endian.c
===
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/negative/big_endian.c
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64_be-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify %s
+
+// expected-error@* {{Big endian is currently not supported for arm_sve.h}}
+#include 
Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret.c
===
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret.c
@@ -0,0 +1,960 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+
+#include 
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+svint8_t test_svreinterpret_s8_s8(svint8_t op)
+{
+  // CHECK-LABEL: test_svreinterpret_s8_s8
+  // CHECK: ret  %op
+  

[PATCH] D78756: [SveEmitter] Add builtins for svreinterpret

2020-05-04 Thread Eli Friedman via Phabricator via cfe-commits
efriedma added inline comments.



Comment at: clang/lib/CodeGen/CGBuiltin.cpp:7880
+return Builder.CreateBitCast(Val, Ty);
+  }
+

efriedma wrote:
> sdesmalen wrote:
> > efriedma wrote:
> > > sdesmalen wrote:
> > > > efriedma wrote:
> > > > > I'm vaguely suspicious this might be wrong for big-endian targets.  I 
> > > > > mean, this isn't unreasonable, but users might be surprised if 
> > > > > svreinterpret isn't a no-op.
> > > > For SVE the loads and stores (svld1 and svst1) are all endian safe, so 
> > > > no special consideration needs to be taken for big endian targets.
> > > > 
> > > > The ACLE specifies that:
> > > > > The svreinterpret functions simply reinterpret a vector of one type 
> > > > > as a vector of another type, without changing any of the bits.
> > > "bitcast" is specified to mean "reinterpret the bits like a store+load".  
> > > On big-endian NEON (and, I assume, SVE), that isn't a no-op.  See 
> > > http://llvm.org/docs/BigEndianNEON.html .
> > > 
> > > I mean, if the answer here is "yes, svreinterpret is supposed to lower to 
> > > a REV", then that's fine.  But I'd like to see some explciit 
> > > acknowledgement that that's intentional.
> > Thanks for pointing out that page, but for SVE I don't think the 
> > svreinterpret should lower to a REV.
> > 
> > This is probably where things are different from Neon. The ACLE SVE vectors 
> > such as `svint32_t` are opaque vector types and the only way to load/store 
> > them from/to memory is through the use of the svld1 and svst1 intrinsics 
> > which are endian safe (in that they use the ld1/st1 instructions that do 
> > endianess conversion on big endian targets). The ACLE does not expose any 
> > full-vector load/store (ldr/str) operations.
> Like that page describes, we use ld1/st1 for big-endian NEON, to match the 
> LLVM IR rules for laying out a vector.  If you use ld1/st1 to load/store 
> vectors on big-endian NEON, a bitcast is not a no-op.  As far as I know, SVE 
> ld1/st1 is equivalent to NEON ld1/st1 in the case where vscale=1.  Therefore, 
> on big-endian SVE, a bitcast is not a no-op.
> 
> That leaves the following options:
> 
> 1. svreinterpret is not a no-op.
> 2. svreinterpret is not equivalent to an LLVM IR bitcast, so this patch needs 
> to be changed.
(If you don't care about big-endian SVE right now, that's fine, but please at 
least leave a FIXME.)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78756/new/

https://reviews.llvm.org/D78756



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D78756: [SveEmitter] Add builtins for svreinterpret

2020-04-29 Thread Eli Friedman via Phabricator via cfe-commits
efriedma added inline comments.



Comment at: clang/lib/CodeGen/CGBuiltin.cpp:7880
+return Builder.CreateBitCast(Val, Ty);
+  }
+

sdesmalen wrote:
> efriedma wrote:
> > sdesmalen wrote:
> > > efriedma wrote:
> > > > I'm vaguely suspicious this might be wrong for big-endian targets.  I 
> > > > mean, this isn't unreasonable, but users might be surprised if 
> > > > svreinterpret isn't a no-op.
> > > For SVE the loads and stores (svld1 and svst1) are all endian safe, so no 
> > > special consideration needs to be taken for big endian targets.
> > > 
> > > The ACLE specifies that:
> > > > The svreinterpret functions simply reinterpret a vector of one type as 
> > > > a vector of another type, without changing any of the bits.
> > "bitcast" is specified to mean "reinterpret the bits like a store+load".  
> > On big-endian NEON (and, I assume, SVE), that isn't a no-op.  See 
> > http://llvm.org/docs/BigEndianNEON.html .
> > 
> > I mean, if the answer here is "yes, svreinterpret is supposed to lower to a 
> > REV", then that's fine.  But I'd like to see some explciit acknowledgement 
> > that that's intentional.
> Thanks for pointing out that page, but for SVE I don't think the 
> svreinterpret should lower to a REV.
> 
> This is probably where things are different from Neon. The ACLE SVE vectors 
> such as `svint32_t` are opaque vector types and the only way to load/store 
> them from/to memory is through the use of the svld1 and svst1 intrinsics 
> which are endian safe (in that they use the ld1/st1 instructions that do 
> endianess conversion on big endian targets). The ACLE does not expose any 
> full-vector load/store (ldr/str) operations.
Like that page describes, we use ld1/st1 for big-endian NEON, to match the LLVM 
IR rules for laying out a vector.  If you use ld1/st1 to load/store vectors on 
big-endian NEON, a bitcast is not a no-op.  As far as I know, SVE ld1/st1 is 
equivalent to NEON ld1/st1 in the case where vscale=1.  Therefore, on 
big-endian SVE, a bitcast is not a no-op.

That leaves the following options:

1. svreinterpret is not a no-op.
2. svreinterpret is not equivalent to an LLVM IR bitcast, so this patch needs 
to be changed.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78756/new/

https://reviews.llvm.org/D78756



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D78756: [SveEmitter] Add builtins for svreinterpret

2020-04-29 Thread Sander de Smalen via Phabricator via cfe-commits
sdesmalen marked an inline comment as done.
sdesmalen added inline comments.



Comment at: clang/lib/CodeGen/CGBuiltin.cpp:7880
+return Builder.CreateBitCast(Val, Ty);
+  }
+

efriedma wrote:
> sdesmalen wrote:
> > efriedma wrote:
> > > I'm vaguely suspicious this might be wrong for big-endian targets.  I 
> > > mean, this isn't unreasonable, but users might be surprised if 
> > > svreinterpret isn't a no-op.
> > For SVE the loads and stores (svld1 and svst1) are all endian safe, so no 
> > special consideration needs to be taken for big endian targets.
> > 
> > The ACLE specifies that:
> > > The svreinterpret functions simply reinterpret a vector of one type as a 
> > > vector of another type, without changing any of the bits.
> "bitcast" is specified to mean "reinterpret the bits like a store+load".  On 
> big-endian NEON (and, I assume, SVE), that isn't a no-op.  See 
> http://llvm.org/docs/BigEndianNEON.html .
> 
> I mean, if the answer here is "yes, svreinterpret is supposed to lower to a 
> REV", then that's fine.  But I'd like to see some explciit acknowledgement 
> that that's intentional.
Thanks for pointing out that page, but for SVE I don't think the svreinterpret 
should lower to a REV.

This is probably where things are different from Neon. The ACLE SVE vectors 
such as `svint32_t` are opaque vector types and the only way to load/store them 
from/to memory is through the use of the svld1 and svst1 intrinsics which are 
endian safe (in that they use the ld1/st1 instructions that do endianess 
conversion on big endian targets). The ACLE does not expose any full-vector 
load/store (ldr/str) operations.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78756/new/

https://reviews.llvm.org/D78756



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D78756: [SveEmitter] Add builtins for svreinterpret

2020-04-29 Thread Eli Friedman via Phabricator via cfe-commits
efriedma added inline comments.



Comment at: clang/lib/CodeGen/CGBuiltin.cpp:7880
+return Builder.CreateBitCast(Val, Ty);
+  }
+

sdesmalen wrote:
> efriedma wrote:
> > I'm vaguely suspicious this might be wrong for big-endian targets.  I mean, 
> > this isn't unreasonable, but users might be surprised if svreinterpret 
> > isn't a no-op.
> For SVE the loads and stores (svld1 and svst1) are all endian safe, so no 
> special consideration needs to be taken for big endian targets.
> 
> The ACLE specifies that:
> > The svreinterpret functions simply reinterpret a vector of one type as a 
> > vector of another type, without changing any of the bits.
"bitcast" is specified to mean "reinterpret the bits like a store+load".  On 
big-endian NEON (and, I assume, SVE), that isn't a no-op.  See 
http://llvm.org/docs/BigEndianNEON.html .

I mean, if the answer here is "yes, svreinterpret is supposed to lower to a 
REV", then that's fine.  But I'd like to see some explciit acknowledgement that 
that's intentional.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78756/new/

https://reviews.llvm.org/D78756



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D78756: [SveEmitter] Add builtins for svreinterpret

2020-04-29 Thread Sander de Smalen via Phabricator via cfe-commits
sdesmalen marked an inline comment as done.
sdesmalen added inline comments.



Comment at: clang/lib/CodeGen/CGBuiltin.cpp:7880
+return Builder.CreateBitCast(Val, Ty);
+  }
+

efriedma wrote:
> I'm vaguely suspicious this might be wrong for big-endian targets.  I mean, 
> this isn't unreasonable, but users might be surprised if svreinterpret isn't 
> a no-op.
For SVE the loads and stores (svld1 and svst1) are all endian safe, so no 
special consideration needs to be taken for big endian targets.

The ACLE specifies that:
> The svreinterpret functions simply reinterpret a vector of one type as a 
> vector of another type, without changing any of the bits.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78756/new/

https://reviews.llvm.org/D78756



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D78756: [SveEmitter] Add builtins for svreinterpret

2020-04-28 Thread Eli Friedman via Phabricator via cfe-commits
efriedma added inline comments.



Comment at: clang/lib/CodeGen/CGBuiltin.cpp:7880
+return Builder.CreateBitCast(Val, Ty);
+  }
+

I'm vaguely suspicious this might be wrong for big-endian targets.  I mean, 
this isn't unreasonable, but users might be surprised if svreinterpret isn't a 
no-op.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D78756/new/

https://reviews.llvm.org/D78756



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D78756: [SveEmitter] Add builtins for svreinterpret

2020-04-23 Thread Sander de Smalen via Phabricator via cfe-commits
sdesmalen created this revision.
sdesmalen added reviewers: SjoerdMeijer, efriedma, ctetreau.
Herald added subscribers: kristof.beyls, tschuett.
Herald added a reviewer: rengolin.
Herald added a project: clang.

The reinterpret builtins are generated separately because they
need the cross product of all types, 121 functions in total,
which is inconvenient to specify in the arm_sve.td file.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D78756

Files:
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret.c
  clang/utils/TableGen/SveEmitter.cpp

Index: clang/utils/TableGen/SveEmitter.cpp
===
--- clang/utils/TableGen/SveEmitter.cpp
+++ clang/utils/TableGen/SveEmitter.cpp
@@ -235,6 +235,23 @@
 
 class SVEEmitter {
 private:
+  // The reinterpret builtins are generated separately because they
+  // need the cross product of all types (121 functions in total),
+  // which is inconvenient to specify in the arm_sve.td file or
+  // generate in CGBuiltin.cpp.
+  struct ReinterpretTypeInfo {
+const char *Suffix;
+const char *Type;
+const char *BuiltinType;
+  };
+  SmallVector Reinterprets = {
+  {"s8", "svint8_t", "q16Sc"},   {"s16", "svint16_t", "q8Ss"},
+  {"s32", "svint32_t", "q4Si"},  {"s64", "svint64_t", "q2SWi"},
+  {"u8", "svuint8_t", "q16Uc"},  {"u16", "svuint16_t", "q8Us"},
+  {"u32", "svuint32_t", "q4Ui"}, {"u64", "svuint64_t", "q2UWi"},
+  {"f16", "svfloat16_t", "q8h"}, {"f32", "svfloat32_t", "q4f"},
+  {"f64", "svfloat64_t", "q2d"}};
+
   RecordKeeper 
   llvm::StringMap EltTypes;
   llvm::StringMap MemEltTypes;
@@ -1053,6 +1070,22 @@
   OS << "#define __aio static inline __attribute__((__always_inline__, "
 "__nodebug__, __overloadable__))\n\n";
 
+  // Add reinterpret functions.
+  for (auto ShortForm : { false, true } )
+for (const ReinterpretTypeInfo  : Reinterprets)
+  for (const ReinterpretTypeInfo  : Reinterprets) {
+if (ShortForm) {
+  OS << "__aio " << From.Type << " svreinterpret_" << From.Suffix;
+  OS << "(" << To.Type << " op) {\n";
+  OS << "  return __builtin_sve_reinterpret_" << From.Suffix << "_"
+ << To.Suffix << "(op);\n";
+  OS << "}\n\n";
+} else
+  OS << "#define svreinterpret_" << From.Suffix << "_" << To.Suffix
+ << "(...) __builtin_sve_reinterpret_" << From.Suffix << "_"
+ << To.Suffix << "(__VA_ARGS__)\n";
+  }
+
   SmallVector, 128> Defs;
   std::vector RV = Records.getAllDerivedDefinitions("Inst");
   for (auto *R : RV)
@@ -1223,8 +1256,16 @@
   OS << "BUILTIN(__builtin_sve_" << Def->getMangledName() << ", \""
  << Def->getBuiltinTypeStr() << "\", \"n\")\n";
   }
+
+  // Add reinterpret builtins
+  for (const ReinterpretTypeInfo  : Reinterprets)
+for (const ReinterpretTypeInfo  : Reinterprets)
+  OS << "BUILTIN(__builtin_sve_reinterpret_" << From.Suffix << "_"
+ << To.Suffix << +", \"" << From.BuiltinType << To.BuiltinType
+ << "\", \"n\")\n";
+
   OS << "#endif\n\n";
-}
+  }
 
 void SVEEmitter::createCodeGenMap(raw_ostream ) {
   std::vector RV = Records.getAllDerivedDefinitions("Inst");
Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret.c
===
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_reinterpret.c
@@ -0,0 +1,960 @@
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -D__ARM_FEATURE_SVE -DSVE_OVERLOADED_FORMS -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - %s | FileCheck %s
+
+#include 
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+svint8_t test_svreinterpret_s8_s8(svint8_t op)
+{
+  // CHECK-LABEL: test_svreinterpret_s8_s8
+  // CHECK: ret  %op
+  return SVE_ACLE_FUNC(svreinterpret_s8,_s8,,)(op);
+}
+
+svint8_t test_svreinterpret_s8_s16(svint16_t op)
+{
+  // CHECK-LABEL: test_svreinterpret_s8_s16
+  // CHECK: %[[CAST:.*]] = bitcast  %op to 
+  // CHECK: ret  %[[CAST]]
+  return SVE_ACLE_FUNC(svreinterpret_s8,_s16,,)(op);
+}
+
+svint8_t test_svreinterpret_s8_s32(svint32_t op)
+{
+  // CHECK-LABEL: test_svreinterpret_s8_s32
+  // CHECK: %[[CAST:.*]] = bitcast  %op to 
+  // CHECK: ret  %[[CAST]]
+  return SVE_ACLE_FUNC(svreinterpret_s8,_s32,,)(op);
+}
+
+svint8_t test_svreinterpret_s8_s64(svint64_t op)
+{
+  // CHECK-LABEL: test_svreinterpret_s8_s64
+  // CHECK: %[[CAST:.*]] = bitcast  %op to 
+  // CHECK: ret  %[[CAST]]
+  return