Hi rjmccall,

Adds type trait "simd_align" after discussions here 
http://reviews.llvm.org/D9894

http://reviews.llvm.org/D10597

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/TargetInfo.h
  include/clang/Basic/TokenKinds.def
  include/clang/Basic/TypeTraits.h
  lib/AST/ASTContext.cpp
  lib/AST/ASTDumper.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/StmtPrinter.cpp
  lib/Basic/TargetInfo.cpp
  lib/Basic/Targets.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/CodeGen/CGStmtOpenMP.cpp
  lib/CodeGen/TargetInfo.cpp
  lib/CodeGen/TargetInfo.h
  lib/Parse/ParseExpr.cpp
  lib/Sema/SemaExpr.cpp
  test/CodeGen/simd_align.c
  test/SemaCXX/simd_align.cpp

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: test/CodeGen/simd_align.c
===================================================================
--- test/CodeGen/simd_align.c
+++ test/CodeGen/simd_align.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -O1 -emit-llvm -o %t %s
+// RUN: grep 'ret i32 16' %t
+
+enum e0 { E0 };
+struct s0 {
+  enum e0         a:31;
+};
+
+struct s0 t1_tmp;
+int f0() {
+  return simd_align(t1_tmp);
+}
Index: test/SemaCXX/simd_align.cpp
===================================================================
--- test/SemaCXX/simd_align.cpp
+++ test/SemaCXX/simd_align.cpp
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -triple x86_64-unknown-unknown -verify %s
+
+struct S0 {
+  int x;
+  static const int test0 = simd_align(x);
+  static const int test1 = simd_align(S0::x);
+  auto test2() -> char(&)[simd_align(x)];
+};
+
+struct S1; // expected-note 6 {{forward declaration}}
+extern S1 s1;
+const int test3 = simd_align(s1); // expected-error {{invalid application of 'simd_align' to an incomplete type 'S1'}}
+
+struct S2 {
+  S2();
+  S1 &s;
+  int x;
+
+  int test4 = simd_align(x); // ok
+  int test5 = simd_align(s); // expected-error {{invalid application of 'simd_align' to an incomplete type 'S1'}}
+};
+
+const int test6 = simd_align(S2::x);
+const int test7 = simd_align(S2::s); // expected-error {{invalid application of 'simd_align' to an incomplete type 'S1'}}
+
+// Arguably, these should fail like the S1 cases do: the alignment of
+// 's2.x' should depend on the alignment of both x-within-S2 and
+// s2-within-S3 and thus require 'S3' to be complete.  If we start
+// doing the appropriate recursive walk to do that, we should make
+// sure that these cases don't explode.
+struct S3 {
+  S2 s2;
+
+  static const int test8 = simd_align(s2.x);
+  static const int test9 = simd_align(s2.s); // expected-error {{invalid application of 'simd_align' to an incomplete type 'S1'}}
+  auto test10() -> char(&)[simd_align(s2.x)];
+  static const int test11 = simd_align(S3::s2.x);
+  static const int test12 = simd_align(S3::s2.s); // expected-error {{invalid application of 'simd_align' to an incomplete type 'S1'}}
+  auto test13() -> char(&)[simd_align(s2.x)];
+};
+
+// Same reasoning as S3.
+struct S4 {
+  union {
+    int x;
+  };
+  static const int test0 = simd_align(x);
+  static const int test1 = simd_align(S0::x);
+  auto test2() -> char(&)[simd_align(x)];
+};
+
+// Regression test for asking for the alignment of a field within an invalid
+// record.
+struct S5 {
+  S1 s;  // expected-error {{incomplete type}}
+  int x;
+};
+const int test8 = simd_align(S5::x);
+
+long long int test14[2];
+
+static_assert(simd_align(test14) == 16, "foo");
+
+static_assert(simd_align(int[2]) == simd_align(int), ""); // ok
+
+namespace simd_align_array_expr {
+  alignas(32) extern int n[2];
+  static_assert(simd_align(n) == 16, "");
+
+  template<int> struct S {
+    static int a[];
+  };
+  template<int N> int S<N>::a[N];
+  static_assert(simd_align(S<1>::a) == simd_align(int), "");
+  static_assert(simd_align(S<1128>::a) == simd_align(int), "");
+}
+
+template <typename T> void n(T) {
+  alignas(T) int T1;
+  char k[simd_align(T1)];
+  static_assert(sizeof(k) == simd_align(long long), "");
+}
+template void n(long long);
Index: include/clang/Basic/TypeTraits.h
===================================================================
--- include/clang/Basic/TypeTraits.h
+++ include/clang/Basic/TypeTraits.h
@@ -92,7 +92,8 @@
   enum UnaryExprOrTypeTrait {
     UETT_SizeOf,
     UETT_AlignOf,
-    UETT_VecStep
+    UETT_VecStep,
+    UETT_OpenMPDefaultSimdAlign,
   };
 }
 
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def
+++ include/clang/Basic/TokenKinds.def
@@ -503,6 +503,9 @@
 KEYWORD(__builtin_astype            , KEYOPENCL)
 KEYWORD(vec_step                    , KEYOPENCL|KEYALTIVEC)
 
+// OpenMP Type Traits
+KEYWORD(simd_align                  , KEYALL)
+
 // Borland Extensions.
 KEYWORD(__pascal                    , KEYALL)
 
Index: include/clang/Basic/TargetInfo.h
===================================================================
--- include/clang/Basic/TargetInfo.h
+++ include/clang/Basic/TargetInfo.h
@@ -70,6 +70,7 @@
   unsigned char MinGlobalAlign;
   unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
   unsigned short MaxVectorAlign;
+  unsigned short SimdDefaultAlign;
   const char *DescriptionString;
   const char *UserLabelPrefix;
   const char *MCountName;
@@ -393,6 +394,8 @@
 
   /// \brief Return the maximum vector alignment supported for the given target.
   unsigned getMaxVectorAlign() const { return MaxVectorAlign; }
+  /// \brief Return default simd alignment for the given target.
+  unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; }
 
   /// \brief Return the size of intmax_t and uintmax_t for this target, in bits.
   unsigned getIntMaxTWidth() const {
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -4684,18 +4684,18 @@
 
 // Expressions.
 def ext_sizeof_alignof_function_type : Extension<
-  "invalid application of '%select{sizeof|alignof|vec_step}0' to a "
+  "invalid application of '%select{sizeof|alignof|vec_step|simd_align} to a "
   "function type">, InGroup<PointerArith>;
 def ext_sizeof_alignof_void_type : Extension<
-  "invalid application of '%select{sizeof|alignof|vec_step}0' to a void "
+  "invalid application of '%select{sizeof|alignof|vec_step|simd_align}0' to a void "
   "type">, InGroup<PointerArith>;
 def err_opencl_sizeof_alignof_type : Error<
-  "invalid application of '%select{sizeof|alignof|vec_step}0' to a void type">;
+  "invalid application of '%select{sizeof|alignof|vec_step|simd_align}0' to a void type">;
 def err_sizeof_alignof_incomplete_type : Error<
-  "invalid application of '%select{sizeof|alignof|vec_step}0' to an "
+  "invalid application of '%select{sizeof|alignof|vec_step|simd_align}0' to an "
   "incomplete type %1">;
 def err_sizeof_alignof_function_type : Error<
-  "invalid application of '%select{sizeof|alignof|vec_step}0' to a "
+  "invalid application of '%select{sizeof|alignof|vec_step|simd_align}0' to a "
   "function type">;
 def err_sizeof_alignof_bitfield : Error<
   "invalid application of '%select{sizeof|alignof}0' to bit-field">;
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -78,10 +78,14 @@
   struct TypeInfo {
     uint64_t Width;
     unsigned Align;
+    unsigned SimdDefaultAlign;
     bool AlignIsRequired : 1;
-    TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {}
-    TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired)
-        : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {}
+    TypeInfo()
+        : Width(0), Align(0), SimdDefaultAlign(0), AlignIsRequired(false) {}
+    TypeInfo(uint64_t Width, unsigned Align, unsigned SimdDefaultAlign,
+             bool AlignIsRequired)
+        : Width(Width), Align(Align), SimdDefaultAlign(SimdDefaultAlign),
+          AlignIsRequired(AlignIsRequired) {}
   };
 
 /// \brief Holds long-lived AST nodes (such as types and decls) that can be
Index: lib/Basic/TargetInfo.cpp
===================================================================
--- lib/Basic/TargetInfo.cpp
+++ lib/Basic/TargetInfo.cpp
@@ -50,6 +50,7 @@
   LargeArrayAlign = 0;
   MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
   MaxVectorAlign = 0;
+  SimdDefaultAlign = 0;
   SizeType = UnsignedLong;
   PtrDiffType = SignedLong;
   IntMaxType = SignedLongLong;
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp
+++ lib/Basic/Targets.cpp
@@ -759,6 +759,7 @@
       HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false),
       HasBPERMD(false), HasExtDiv(false) {
     BigEndian = (Triple.getArch() != llvm::Triple::ppc64le);
+    SimdDefaultAlign = 16;
     LongDoubleWidth = LongDoubleAlign = 128;
     LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble;
   }
@@ -2972,6 +2973,8 @@
     Features.erase(it);
   else if (SSELevel > NoSSE)
     MMX3DNowLevel = std::max(MMX3DNowLevel, MMX);
+
+  SimdDefaultAlign = (getABI() == "avx") ? 32 : 16;
   return true;
 }
 
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -3518,7 +3518,8 @@
 
   // C99 6.5.3.4p1:
   if (T->isFunctionType() &&
-      (TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf)) {
+      (TraitKind == UETT_SizeOf || TraitKind == UETT_AlignOf ||
+       TraitKind == UETT_OpenMPDefaultSimdAlign)) {
     // sizeof(function)/alignof(function) is allowed as an extension.
     S.Diag(Loc, diag::ext_sizeof_alignof_function_type)
       << TraitKind << ArgRange;
@@ -3620,7 +3621,8 @@
 
   // The operand for sizeof and alignof is in an unevaluated expression context,
   // so side effects could result in unintended consequences.
-  if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf) &&
+  if ((ExprKind == UETT_SizeOf || ExprKind == UETT_AlignOf ||
+       ExprKind == UETT_OpenMPDefaultSimdAlign) &&
       ActiveTemplateInstantiations.empty() && E->HasSideEffects(Context, false))
     Diag(E->getExprLoc(), diag::warn_side_effects_unevaluated_context);
 
@@ -3824,6 +3826,9 @@
     isInvalid = CheckAlignOfExpr(*this, E);
   } else if (ExprKind == UETT_VecStep) {
     isInvalid = CheckVecStepExpr(E);
+  } else if (ExprKind == UETT_OpenMPDefaultSimdAlign) {
+    isInvalid =
+        CheckUnaryExprOrTypeTraitOperand(E, UETT_OpenMPDefaultSimdAlign);
   } else if (E->refersToBitField()) {  // C99 6.5.3.4p1.
     Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0;
     isInvalid = true;
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -7251,6 +7251,12 @@
       return false;
     return Success(Sizeof, E);
   }
+  case UETT_OpenMPDefaultSimdAlign:
+    return Success(Info.Ctx.getTypeInfo(E->isArgumentType()
+                                            ? E->getArgumentType()
+                                            : E->getArgumentExpr()->getType())
+                       .SimdDefaultAlign,
+                   E);
   }
 
   llvm_unreachable("unknown expr/type trait");
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -3018,7 +3018,14 @@
     case UETT_AlignOf:
       Out << 'a';
       break;
-    case UETT_VecStep:
+    case UETT_VecStep: {
+      DiagnosticsEngine &Diags = Context.getDiags();
+      unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
+                                     "cannot yet mangle vec_step expression");
+      Diags.Report(DiagID);
+      return;
+    }
+    case UETT_OpenMPDefaultSimdAlign:
       DiagnosticsEngine &Diags = Context.getDiags();
       unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
                                      "cannot yet mangle vec_step expression");
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp
+++ lib/AST/StmtPrinter.cpp
@@ -1206,6 +1206,9 @@
   case UETT_VecStep:
     OS << "vec_step";
     break;
+  case UETT_OpenMPDefaultSimdAlign:
+    OS << "simd_align";
+    break;
   }
   if (Node->isArgumentType()) {
     OS << '(';
Index: lib/AST/ASTDumper.cpp
===================================================================
--- lib/AST/ASTDumper.cpp
+++ lib/AST/ASTDumper.cpp
@@ -1825,6 +1825,9 @@
   case UETT_VecStep:
     OS << " vec_step";
     break;
+  case UETT_OpenMPDefaultSimdAlign:
+    OS << "simd_align";
+    break;
   }
   if (Node->isArgumentType())
     dumpType(Node->getArgumentType());
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -1481,6 +1481,13 @@
   uint64_t Width = 0;
   unsigned Align = 8;
   bool AlignIsRequired = false;
+  unsigned SimdAlign = getTargetInfo().getSimdDefaultAlign();
+  // Target ppc64 with QPX: simd default alignment for pointer to double is 32.
+  if ((getTargetInfo().getTriple().getArch() == llvm::Triple::ppc64 ||
+       getTargetInfo().getTriple().getArch() == llvm::Triple::ppc64le) &&
+      getTargetInfo().getABI() == "elfv1-qpx" && T->isAnyPointerType() &&
+      T->getPointeeType()->isSpecificBuiltinType(BuiltinType::Double))
+    SimdAlign = 32;
   switch (T->getTypeClass()) {
 #define TYPE(Class, Base)
 #define ABSTRACT_TYPE(Class, Base)
@@ -1783,7 +1790,7 @@
   }
 
   assert(llvm::isPowerOf2_32(Align) && "Alignment must be power of 2");
-  return TypeInfo(Width, Align, AlignIsRequired);
+  return TypeInfo(Width, Align, SimdAlign, AlignIsRequired);
 }
 
 /// toCharUnitsFromBits - Convert a size in bits to a size in characters.
Index: lib/CodeGen/TargetInfo.cpp
===================================================================
--- lib/CodeGen/TargetInfo.cpp
+++ lib/CodeGen/TargetInfo.cpp
@@ -1628,10 +1628,6 @@
             ('T' << 24);
     return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
   }
-
-  unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
-    return getABIInfo().hasAVX() ? 32 : 16;
-  }
 };
 
 class PS4TargetCodeGenInfo : public X86_64TargetCodeGenInfo {
@@ -1737,10 +1733,6 @@
                                llvm::SmallString<32> &Opt) const override {
     Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
   }
-
-  unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
-    return hasAVX() ? 32 : 16;
-  }
 };
 
 void WinX86_64TargetCodeGenInfo::setTargetAttributes(const Decl *D,
@@ -3145,10 +3137,6 @@
 
   bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
                                llvm::Value *Address) const override;
-
-  unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
-    return 16; // Natural alignment for Altivec vectors.
-  }
 };
 
 }
@@ -3388,30 +3376,19 @@
 };
 
 class PPC64_SVR4_TargetCodeGenInfo : public TargetCodeGenInfo {
-  bool HasQPX;
 
 public:
   PPC64_SVR4_TargetCodeGenInfo(CodeGenTypes &CGT,
                                PPC64_SVR4_ABIInfo::ABIKind Kind, bool HasQPX)
-    : TargetCodeGenInfo(new PPC64_SVR4_ABIInfo(CGT, Kind, HasQPX)),
-      HasQPX(HasQPX) {}
+      : TargetCodeGenInfo(new PPC64_SVR4_ABIInfo(CGT, Kind, HasQPX)) {}
 
   int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
     // This is recovered from gcc output.
     return 1; // r1 is the dedicated stack pointer
   }
 
   bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
                                llvm::Value *Address) const override;
-
-  unsigned getOpenMPSimdDefaultAlignment(QualType QT) const override {
-    if (HasQPX)
-      if (const PointerType *PT = QT->getAs<PointerType>())
-        if (PT->getPointeeType()->isSpecificBuiltinType(BuiltinType::Double))
-          return 32; // Natural alignment for QPX doubles.
-
-    return 16; // Natural alignment for Altivec and VSX vectors.
-  }
 };
 
 class PPC64TargetCodeGenInfo : public DefaultTargetCodeGenInfo {
@@ -3425,10 +3402,6 @@
 
   bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
                                llvm::Value *Address) const override;
-
-  unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
-    return 16; // Natural alignment for Altivec vectors.
-  }
 };
 
 }
Index: lib/CodeGen/TargetInfo.h
===================================================================
--- lib/CodeGen/TargetInfo.h
+++ lib/CodeGen/TargetInfo.h
@@ -218,13 +218,6 @@
   virtual void getDetectMismatchOption(llvm::StringRef Name,
                                        llvm::StringRef Value,
                                        llvm::SmallString<32> &Opt) const {}
-
-  /// Gets the target-specific default alignment used when an 'aligned' clause
-  /// is used with a 'simd' OpenMP directive without specifying a specific
-  /// alignment.
-  virtual unsigned getOpenMPSimdDefaultAlignment(QualType Type) const {
-    return 0;
-  }
 };
 }
 
Index: lib/CodeGen/CGExprScalar.cpp
===================================================================
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -16,6 +16,7 @@
 #include "CGDebugInfo.h"
 #include "CGObjCRuntime.h"
 #include "CodeGenModule.h"
+#include "TargetInfo.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/RecordLayout.h"
@@ -2037,6 +2038,10 @@
 
       return size;
     }
+  } else if (E->getKind() == UETT_OpenMPDefaultSimdAlign) {
+    auto Alignment =
+        CGF.getContext().getTypeInfo(E->getTypeOfArgument()).SimdDefaultAlign;
+    return Builder.getInt32(Alignment);
   }
 
   // If this isn't sizeof(vla), the result must be constant; use the constant
Index: lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- lib/CodeGen/CGStmtOpenMP.cpp
+++ lib/CodeGen/CGStmtOpenMP.cpp
@@ -648,9 +648,7 @@
         // OpenMP [2.8.1, Description]
         // If no optional parameter is specified, implementation-defined default
         // alignments for SIMD instructions on the target platforms are assumed.
-        Alignment =
-            CGF.CGM.getTargetCodeGenInfo().getOpenMPSimdDefaultAlignment(
-                E->getType());
+        Alignment = CGF.getContext().getTypeInfo(E->getType()).SimdDefaultAlign;
       }
       assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
              "alignment is not power of 2");
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -1042,6 +1042,8 @@
   case tok::kw_sizeof:     // unary-expression: 'sizeof' unary-expression
                            // unary-expression: 'sizeof' '(' type-name ')'
   case tok::kw_vec_step:   // unary-expression: OpenCL 'vec_step' expression
+  // unary-expression: OpenMP 'default simd alignment' expression
+  case tok::kw_simd_align:
     return ParseUnaryExprOrTypeTraitExpression();
   case tok::ampamp: {      // unary-expression: '&&' identifier
     SourceLocation AmpAmpLoc = ConsumeToken();
@@ -1636,8 +1638,9 @@
                                            ParsedType &CastTy,
                                            SourceRange &CastRange) {
 
-  assert(OpTok.isOneOf(tok::kw_typeof,  tok::kw_sizeof,   tok::kw___alignof,
-                       tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step) &&
+  assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof,
+                       tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step,
+                       tok::kw_simd_align) &&
          "Not a typeof/sizeof/alignof/vec_step expression!");
 
   ExprResult Operand;
@@ -1722,7 +1725,7 @@
 /// \endverbatim
 ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
   assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof,
-                     tok::kw__Alignof, tok::kw_vec_step) &&
+                     tok::kw__Alignof, tok::kw_vec_step, tok::kw_simd_align) &&
          "Not a sizeof/alignof/vec_step expression!");
   Token OpTok = Tok;
   ConsumeToken();
@@ -1792,6 +1795,8 @@
     ExprKind = UETT_AlignOf;
   else if (OpTok.is(tok::kw_vec_step))
     ExprKind = UETT_VecStep;
+  else if (OpTok.is(tok::kw_simd_align))
+    ExprKind = UETT_OpenMPDefaultSimdAlign;
 
   if (isCastExpr)
     return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to